题目来自网络,声称这是一道微软的面试题。
先来看看题目:
输入一棵二叉查找树,将该二叉查找树转换成一个排序的双向链表。
要求不能创建任何新的结点,只调整指针的指向。
比如将二叉查找树
10
/ \
6 14
/ \ / \
4 8 12 16
转换成双向链表
4=6=8=10=12=14=16。
仔细分析一下,这并不是一道难题。
回忆一下二叉查找树(binary search tree),如果采用中序遍历,就可以得到有序的遍历结果。
于是,选用递归类似中序遍历的方式来解决这个问题
(1)左子树转化成排序的双向链表
(2)左子树的最后一个结点与根结点双向链接
(3)右子树转化成排序的双向链表
(4)根节点与右子树的第一个结点双向链接
代码如下:
#include <stdlib.h>
#include <stdio.h>
typedef struct SNode{
SNode* left;
SNode* right;
int value;
SNode(int v_):left(NULL),right(NULL){value = v_; }
}Node;
Node* convert_2_double_link_list(Node * root)
{
if (!root) return NULL;
Node* pre = convert_2_double_link_list(root->left);
if (pre) {
//find the end of list
Node* p = pre;
while(p->right != NULL) {
p = p->right;
}
root->left = p;
p->right = root;
} else {
pre = root;
root->left = NULL;
}
Node * post = convert_2_double_link_list(root->right);
if (post) {
post->left = root;
root->right = post;
} else {
root->right = NULL;
}
return pre;
}
void visit(Node* p)
{
while (p){
printf("%d->\n",p->value);
p = p->right;
}
}
int main()
{
Node * root = new Node(10);
Node * r11 = new Node(6);
root->left = r11;
Node * r12 = new Node(14);
root->right = r12;
Node * r21 = new Node(4);
r11->left = r21;
Node * r22 = new Node(8);
r11->right = r22;
Node * r31 = new Node(12);
r12->left = r31;
Node * r32 = new Node(16);
r12->right = r32;
Node* p = convert_2_double_link_list(root);
visit(p);
//system("pause");
return 0;
}
解答完毕之后看到这篇文章的解法
http://blog.csdn.net/sjf0115/article/details/7707647
这个blog中提到了2种不同的实现方法,甚好:
(1)第一种与本文中的方法相似,不过文中,标记了是左子还是右子,来决定最后返回部分排序好的头节点还是尾节点。
(2)第二种方式,就是直接采取中序遍历,用一个指向双向链表队尾的指针记录中序遍历访问的节点。