【经典数据结构算法】(1)二叉查找树与双向链表之间的转换

题目参看csdn上的一个很经典的帖子,http://topic.csdn.net/u/20101126/10/b4f12a00-6280-492f-b785-cb6835a63dc9.html?60918。但代码都是自己使用C语言写的,思路基本上都是自己想出的,如果参考了帖子上别人的思想,则会注明。

  1 /*
2 * 将二元查找树转变为排序的双向链表
3 * 题目:输入一颗二元查找树,将该二元查找树转换成一个排序的双向链表
4 * 要求不能创建任何新的结点,只调整指针的指向。
5 * 如:
6 * 10
7 * / \
8 * 6 14
9 * / \ / \
10 * 4 8 12 16
11 *
12 * 转换成:4=6=10=12=16
13 *
14 */
15 // [10/1/2011 Chenny]
16 /*
17 * 分析:
18 * 二元查找树实质上是这样的一种二叉树:每个结点的值均小于左子结点的值,而大于右子结点的值。
19 * 要让二元查找树转换成排序的双向链表而不创建任何结点,就需要斟酌考虑如何调整结点之间的指针。
20 * 在二元查找树中,最小的值一定是最左结点,其次是最左节点的父节点,再次是该父节点的右子结点(如果存在的话)。
21 * 最大的结点与最小的结点相似,只是左右颠倒:最大的值一定是最右结点……
22 * 通过分析二元查找树的结点的连接情况,可以很显然地知道,如果要按照顺序遍历它,就是那种最基本的遍历:前序遍历(先序遍历)。
23 * 那么就通过最基本的前序遍历方法:递归来实现。
24 * 接下来最重要的一件事情就是如何调整相关联的两个结点指针。下面考虑如何调整指针。
25 * 在处理一个结点,将它从二元查找树上“弄到”双向链表上的时候,它已经没有了左孩子,否则,就不应该在这个时候处理该结点。
26 * 而应该去处理它的左子结点。那么,在处理该结点的时候,我们应该怎么做呢?最简单的方法就是创建一个结点指针
27 * 注意,不是结点,而是指针,这样才符合题目要求。它指向双向链表的最后一个元素,用来将二元查找树中的元素摘下,放到双向链表中。
28 * 记得在放到双向链表中的时候,不要处理该结点的右子指针,因为我们还没有处理过比它大的结点。
29 * 以上即是基本的分析,下面用程序来实现
30 */
31 #include
32 #include
33 #include
34 /*
35 * 定义二叉树的结构
36 */
37 typedef struct TreeNode *link;
38 struct TreeNode
39 {
40 int value;
41 link LeftChild;
42 link RightChild;
43 };
44 /*
45 * list为双向排序链表
46 */
47 link list=NULL;
48 /*
49 * 定义结点初始化函数,用来方便生成树
50 */
51 link initNode(int i)
52 {
53 link t=(link)malloc(sizeof(*t));
54 t->value=i;
55 t->LeftChild=NULL;
56 t->RightChild=NULL;
57 return t;
58 }
59 /*
60 * visit函数递归调用,前序遍历二元查找树的每一个结点
61 * 并在适当的时候,将结点插入到双向排序链表中
62 */
63 void visit(link t)
64 {
65 /*
66 * 递归左子
67 */
68 if(t->LeftChild!=NULL)
69 {
70 visit(t->LeftChild);
71 }
72 /*
73 * 处理当前结点
74 */
75 if(list==NULL) //说明当前结点是最小的结点
76 {
77 list=t;
78 t->LeftChild=NULL;
79 }
80 else //list已经非空
81 {
82 list->RightChild=t;
83 t->LeftChild=list;
84 list=t;
85 }
86 /*
87 * 递归右子
88 */
89 if(t->RightChild!=NULL)
90 {
91 visit(t->RightChild);
92 }
93 }
94 int main(void)
95 {
96 /*
97 * 产生测试数据
98 */
99 link root=initNode(10);
100 root->LeftChild=initNode(6);
101 root->RightChild=initNode(14);
102 root->LeftChild->LeftChild=initNode(4);
103 root->LeftChild->RightChild=initNode(8);
104 root->RightChild->LeftChild=initNode(12);
105 root->RightChild->RightChild=initNode(16);
106 visit(root);
107 printf("下面开始逆序输出:\n");
108 while(list->LeftChild!=NULL)
109 {
110 printf("%d\t",list->value);
111 list=list->LeftChild;
112 }
113 printf("%d\n",list->value);
114
115 printf("下面开始正序输出:\n");
116 while(list->RightChild!=NULL)
117 {
118 printf("%d\t",list->value);
119 list=list->RightChild;
120 }
121 printf("%d\n",list->value);
122 return 0;
123 }

测试数据的结果:

【经典数据结构算法】(1)二叉查找树与双向链表之间的转换_第1张图片

你可能感兴趣的:(数据结构)