【經典數據結構算法】(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 <StdAfx.h>
32 #include <stdlib.h>
33 #include <stdio.h>
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 }

測試數據的結果:

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章