微软面试100题系列-第1题
来源:互联网 发布:微博桌面2015网络异常 编辑:程序博客网 时间:2024/05/16 19:25
写文的目的是锻炼自己,欢迎各位大牛提出建议,批评指正~
第一题:把二分查找树转变成排序的双向链表
输入一棵二分查找树,将该二分查找树转换成一个排序的双向链表。要求不能创建任何新的结点,只调整指针的指向。如:
10
/ \
6 14
/ \ / \
4 8 12 16
转换成双向链表4=6=8=10=12=14=16 。
我们定义的二分查找树结点的数据结构如下:
struct BSTreeNode
{
int m_nValue; // value of node
BSTreeNode *m_pLeft; // left child of node
BSTreeNode *m_pRight; // right child of node
};
我的解题思路如下:
本题中不能建立新的结点,只能改变指针的指向。先观察根结点,根据二叉查找树的特点,可以发现根结点的左指针应该指向左子树双向链表的尾部,而根结点的右指针
应该指向右子树双向链表的头部。因此该问题可以递归为求解左、右孩子的双向链表。求解完左、右孩子的双向链表后,再接上根结点,即可完成对双向链表的求解。
根据上述思路,先来看一下代码结构,之后会有例子讲解。
编写如下的递归函数:
void ConvertRecursive(BSTNode* &subHead, BSTNode* &subTail, BSTNode* subRoot)
然后在函数中求解左、右孩子的双向链表:
BSTNode *leftTail = NULL, *rightHead = NULL;
ConvertRecursive(subHead,leftTail,subRoot->pLeft); //求解左子的链表
ConvertRecursive(rightHead,subTail,subRoot->pRight); //求解右子的链表
。。。。。。 //将左子链表、根、右子链表连接起来
这个递归初看可能有点不清晰,我们可以先看一下求解左子链表的语句:
ConvertRecursive(subHead,leftTail,subRoot->pLeft);
这个subHead可看成是当前链表的头,在递归结束后,最上一层的subHead将是整个双向链表的头。而leftTail是我们想要的左孩子双向链表的尾部。
ConvertRecursive(rightHead,subTail,subRoot->pRight);
rightHead是我们想要的右孩子双向链表的头部,而subTail可看成是当前链表的尾,在递归结束后,最上一层的subTail将是整个双向链表的尾。
现在看一下左子链表、根与右子链表连接的操作:如果左子没有双向链表,那么根结点就成为当前链表的头;如果有,根结点就连接上左子链表的尾部。
同理,如果右子没有链表,那么根结点就成为当前链表的尾;如果有,则根结点与右子链表的头部相连接。
//连接左子链表与根
if (leftTail == NULL) //左子没有双向链表
{
subHead = subRoot;
}
else
{
leftTail->pRight = subRoot;
subRoot->pLeft = leftTail;
}//连接右子链表与根
if (rightHead == NULL) //右子没有双向链表
{
subTail = subRoot;
}
else
{
subRoot->pRight = rightHead;
rightHead->pLeft = subRoot;
}
以子树 6 为例,
/ \
4 8
递归到4时,因为4是叶子结点,其左、右子树链表为空,则有subHead -> 4, subTail -> 4。同理8也是这种情况。
返回到6的调用,因为6调用4的递归中,形参subTail实际上是实参leftTail的引用,因此6的左子链表leftTail->4不为空,按照之前的思路,我们可以将结点6与左子链表连
接起来,就有了链表4=6;同理,在6调用8的递归中,形参subHead实际上是实参rightHead的引用,因此6的右子链表rightHead->8也不为空,将6与右子链表连接起来,我们
有了双向链表4=6=8,而此时当前链表的subHead->4,subTail->8。
由此,可以看出整个递归过程中,leftTail和rightHead起到了连接整个链表中间结点的作用,而subHead和subTail则保存了目前递归层次中的最小和最大值。
完整的代码如下,因为自己有一个BST树结点的模板类,所以直接拿来用了,BSTNode<int>和题目中的BSTreeNode的结构是一样的。
//written by zero#include "BST.h"#include <iostream>using namespace std;void ConvertRecursive(BSTNode<int>* &subHead, BSTNode<int>* &subTail, BSTNode<int>* subRoot){ BSTNode<int> *leftTail = NULL, *rightHead = NULL; if (subRoot == NULL) { subHead = NULL; subTail = NULL; return; } ConvertRecursive(subHead,leftTail,subRoot->pLeft); //求解左子的链表 ConvertRecursive(rightHead,subTail,subRoot->pRight); //求解右子的链表 //将左子链表,根,右子链表接在一起 //连接左子链表与根 if (leftTail == NULL) //左子没有双向链表 { subHead = subRoot; } else { leftTail->pRight = subRoot; subRoot->pLeft = leftTail; } //连接右子链表与根 if (rightHead == NULL) //右子没有双向链表 { subTail = subRoot; } else { subRoot->pRight = rightHead; rightHead->pLeft = subRoot; }}int main(){//建立二叉查找树BSTree<int> tree;tree.Insert(10);tree.Insert(6);tree.Insert(14);tree.Insert(4);tree.Insert(8);tree.Insert(12);tree.Insert(16);/*tree.TravelRecursive(&BSTree<int>::PosOderRecursive,&BSTree<int>::process);cout << endl;tree.TravelRecursive(&BSTree<int>::PosOderNonRecursive,&BSTree<int>::process);cout << endl;*///转换成双向链表BSTNode<int> *head = NULL, *tail = NULL, *pNode;ConvertRecursive(head,tail,tree.root);//验证正向遍历双向链表cout << "正向遍历链表:";pNode = head;while(pNode){cout << pNode->value << " ";pNode = pNode->pRight;}cout << endl;//验证逆向遍历双向链表cout << "逆向遍历链表:";pNode = tail;while(pNode){cout << pNode->value << " ";pNode = pNode->pLeft;}cout << endl;}
运行结果如下:
- 微软面试100题系列-第1题
- 微软面试100系列 第32题
- 微软面试100题系列-第2题
- 微软面试100题系列-第3题
- 微软等面试100题系列 - 41
- 微软等面试100题系列--(1-20)
- 微软面试100题系列---求1+2+3+...+n
- 微软面试100题系列:一道合并链表问题的解答[第42题]
- 微软面试100题之第1题
- 微软面试100题之第1题
- 算法面试:精选微软经典的算法面试100题(第1-20题)
- 算法面试:精选微软经典的算法面试100题(第1-20题)
- 算法面试:精选微软经典的算法面试100题(第1-20题)
- 永久勘误:微软等面试100题系列,答案V0.4版[第41-60题答案]
- 永久勘误:微软等面试100题系列,答案V0.4版[第41-60题答案]
- 永久勘误:微软等面试100题系列,答案V0.4版[第41-60题答案]
- 永久勘误:微软等面试100题系列,答案V0.4版[第41-60题答案]
- 永久勘误:微软等面试100题系列,答案V0.4版[第41-60题答案]
- Android中Service方式使用的理解
- javascript :简单的小技巧
- 解决硬盘文件系统raw问题
- linux解压 tar命令
- unity3d版本更新日志
- 微软面试100题系列-第1题
- tar命令的C参数
- System.DateTime.Now.ToString()日常用法
- WinDbug 配置
- linux下dd命令详解
- android时钟显示
- java对字符串操作大全
- 数据库方面的面试题
- 基于android的旅游攻略应用(含源码)