把二元查找树转变成排序的双向链表
题目:输入一棵二元查找树,将该二元查找树转换成一个排序的双向链表。要求不能创建任何新的结点,只调整指针的指向。
比如将二元查找树
10
/ \
6 14
/ \ / \
4 8 12 16
转换成双向链表
4=6=8=10=12=14=16。
分析:这是一道关于二叉树和链表的算法题,据说也是一道微软面试题,见到树,大家一般都会第一时间想到用递归发解决,我们不妨就从这个方向进行考虑.
将二叉查找树转换成链表,如果允许增加结点,就并不是一件很困难的事,因为我们可以发现,通过中序遍历,我们就可以得到一个排好序的数列.但是本题仅允许改变指针的指向,我们可以看到,二叉树每个结点本身已经有两个指针域,并且由于二叉查找树本身的性质,结点左边的值永远比该结点小,结点右边的值永远比该结点大,我们可以每次都假设一个结点的左右两端都是已经排序好的双链表,它左边的所有值一定比它小,它右边的所有值一定比它大,因此,修改这三个结点的指针指向就可以链接成一个排好序的链表.
解答代码:
2 {
3 int data;
4 BSTree *left;
5 BSTree *right;
6} * myTree;
7 myTree Sort(myTree root, bool asright)
8 {
9 myTree lNode,rNode,temp;
10 if(root == NULL)
11 return NULL;
12 //将左边的列表加到root结点的前端
13 if(root->left != NULL)
14 {
15 lNode = Sort(root->left,false);
16 root->left = lNode;
17 lNode->right = root;
18 }
19 //将右边的列表加到root结点的后端
20 if(root->right != NULL)
21 {
22 rNode = Sort(root->right,true);
23 root->right = rNode;
24 rNode->left = root;
25 }
26 //选择边界结点返回
27 if(!asright)//判断是否为右孩子
28 {
29 temp = root;
30 while(temp->right != NULL)
31 temp = temp->right;
32 return temp;
33 }
34 else if(asright)
35 {
36 temp = root;
37 while(temp->left != NULL)
38 temp = temp->left;
39 return temp;
40 }
41
42}
43 int main( int argc, char * argv[])
44 {
45 myTree root,lNode,rNode,temp;
46 root = CreateTree();//建立二叉查找树
47 lNode = Sort(root->left,false);
48 rNode = Sort(root->right,false);
49 root->left = lNode;
50 lNode->right = root;
51 root->right = rNode;
52 rNode->left = root;
53 temp = root;
54 while(temp->left != NULL)
55 temp = temp->left;
56 while(temp != NULL)
57 {
58 printf("%d ",temp->data);
59 temp = temp->right;
60
61 }
62
63 return 0;
64}