码迷,mamicode.com
首页 > 其他好文 > 详细

C实现二叉树(模块化集成,遍历的递归与非递归实现)

时间:2015-07-09 11:08:12      阅读:114      评论:0      收藏:0      [点我收藏+]

标签:

C实现二叉树模块化集成

实验源码介绍(源代码的总体介绍):
header.h : 头文件链栈,循环队列,二叉树的结构声明和相关函数的声明。
LinkStack.c : 链栈的相关操作函数定义。
Queue.c : 循环队列的相关操作函数定义。
BinTree.c : 二叉树的相关操作的函数定义,层序序列生成二叉树,二叉树的前序序列、中序序列、后序序列的递归和非递归实现,求叶子结点的递归与非递归实现,求树高。
我目前还是新手且第一次写类似的博客,文章中难免会有错误!如发现错误,望各路大神能够指出!
详见源代码!

 

 

源代码:header.h

技术分享
 1 /**
 2  * BinTree
 3  */
 4 typedef int BinTree_Type;
 5 typedef struct TreeNode BinTree;
 6 struct TreeNode {
 7     BinTree_Type Data;
 8     BinTree *Left;
 9     BinTree *Right;
10 };
11 
12 /**
13  * Queue
14  */
15 #define MaxSize 50
16 typedef BinTree * Q_ElementType;
17 typedef struct {
18     Q_ElementType Data[MaxSize];
19     int front;
20     int rear;
21 } Queue;
22 
23 extern Queue * InitQueue();
24 extern void Destory(Queue * q);
25 extern int IsQueueEmpty(Queue *q);
26 extern void EnQueue(Queue *q, Q_ElementType e);
27 extern Q_ElementType DeQueue(Queue* q);
28 
29 
30 /**
31  * LinkStack
32  */
33 typedef BinTree * L_ElementType;
34 typedef struct Node {
35     L_ElementType Data;
36     struct Node *next;
37 } LinkStack;
38 
39 extern LinkStack * InitStack();
40 extern int IsStackEmpty(LinkStack *s);
41 extern void Push(LinkStack *s, L_ElementType e);
42 extern L_ElementType Pop(LinkStack *s);
43 extern L_ElementType getTop(LinkStack *s);
header.h

 

 

 

 

源代码:LinkStack.c

技术分享
 1 #include <stdio.h> //standard input output 标准输入输出头文件
 2 #include <malloc.h> //memory allocation分配
 3 #include "header.h"
 4 
 5 
 6 /**
 7  * 初始化一个头结点为空的Stack
 8  * init a stack with a NULL head
 9  */
10 LinkStack * InitStack() {
11     LinkStack *s = (LinkStack *) malloc(sizeof(LinkStack));
12     s->next = NULL;
13     return s;
14 }
15 
16 /**
17  * 若stack为空返回1,否则返回0
18  */
19 int IsStackEmpty(LinkStack *s) {
20     return s->next == NULL;
21 }
22 
23 /**
24  * 入栈
25  */
26 void Push(LinkStack *s, L_ElementType e) {
27     struct Node *p;
28     p = (LinkStack *) malloc(sizeof(LinkStack));
29     p->Data = e;
30     p->next = s->next;
31     s->next = p;
32 }
33 
34 /**
35  * 出栈
36  */
37 L_ElementType Pop(LinkStack *s) {
38     if (s->next == NULL) {
39         printf("Stack is NULL");
40         return NULL;
41     }
42     L_ElementType TopElem;
43     struct Node *top;
44     top = s->next;
45     s->next = top->next;
46     TopElem = top->Data;
47     free(top);
48     return TopElem;
49 }
50 
51 /**
52  * 返回栈顶元素
53  */
54 L_ElementType getTop(LinkStack *s) {
55     if (s->next == NULL) {
56         printf("Stack is NULL");
57         return NULL;
58     }
59     return s->next->Data;
60 }
LinkStack.c

 

 

源代码:Queue.c

技术分享
 1 #include <stdio.h>
 2 #include <malloc.h>
 3 #include "header.h"
 4 
 5 /**
 6  * 初始化循环队列
 7  */
 8 Queue * InitQueue() {
 9     Queue *q = (Queue *) malloc(sizeof(Queue));
10     q->front = q->rear = 0;
11     return q;
12 }
13 
14 /**
15  * 销毁队列
16  */
17 void Destory(Queue * q) {
18     free(q);
19 }
20 
21 /**
22  * 判断队列是否为空
23  */
24 int IsQueueEmpty(Queue *q) {
25     return q->front == q->rear;
26 }
27 
28 /**
29  * 入队
30  */
31 void EnQueue(Queue *q, Q_ElementType e) {
32     if ((q->rear + 1) % MaxSize == q->front) {
33         printf("队列满了");
34         return;
35     }
36     q->rear = (q->rear + 1) % MaxSize;
37     q->Data[q->rear] = e;
38 }
39 
40 /**
41  * 出队
42  */
43 Q_ElementType DeQueue(Queue* q) {
44     if (q->front == q->rear) {
45         printf("队列空了!");
46         return NULL;
47     }
48     q->front = (q->front + 1) % MaxSize;
49     return q->Data[q->front];
50 }
Queue.c

 

 

源代码:BinTree.c

技术分享
  1 #include <stdio.h>
  2 #include <malloc.h>
  3 #include "header.h"
  4 
  5 /**
  6  * 访问
  7  */
  8 void Visited(BinTree *BT) {
  9     printf("%d ", BT->Data);
 10 }
 11 
 12 /**
 13  * 层序生成二叉树
 14  */
 15 BinTree *CreateBinTree() {
 16     BinTree_Type Data;
 17     BinTree *BT = NULL, *T = NULL;
 18     Queue * Q = NULL;
 19     Q = InitQueue();         /* 生成一个队列 */
 20     scanf("%d", &Data);         /* 建立第一个结点,即根节点 */
 21     if (Data) {         /* 分配结点单元,并将结点地址入队 */
 22         BT = (BinTree *) malloc(sizeof(BinTree));
 23         BT->Data = Data;
 24         EnQueue(Q, BT);
 25     } else {
 26         return NULL;        /* 若第一个数据就是0,则返回空树 */
 27     }
 28     while (!IsQueueEmpty(Q)) {
 29         T = DeQueue(Q);         /* 从队列中取出一结点地址 */
 30         scanf("%d", &Data);         /* 读入T的左孩子 */
 31         if (Data) {         /* 分配新结点,作为出对结点左孩子 */
 32             T->Left = (BinTree *) malloc(sizeof(BinTree));
 33             T->Left->Data = Data;
 34             EnQueue(Q, T->Left);         /* 新结点入队 */
 35         } else {
 36             T->Left = NULL;
 37         }
 38         scanf("%d", &Data);         /* 读入T的右孩子 */
 39         if (Data) {         /* 分配新结点,作为出对结点右孩子 */
 40             T->Right = (BinTree *) malloc(sizeof(BinTree));
 41             T->Right->Data = Data;
 42             EnQueue(Q, T->Right);             /* 新结点入队 */
 43         } else {
 44             T->Right = NULL;
 45         }
 46     }         /* 结束while */
 47     return BT;
 48 }
 49 
 50 /**
 51  * 遍历二叉树 递归算法
 52  */
 53 void PreOrderTraversal(BinTree *BT) {
 54     if (BT) {         //BT != NULL
 55         Visited(BT);
 56         PreOrderTraversal(BT->Left);
 57         PreOrderTraversal(BT->Right);
 58     }
 59 }
 60 
 61 void InOrderTraversal(BinTree *BT) {
 62     if (BT) {
 63         InOrderTraversal(BT->Left);
 64         Visited(BT);
 65         InOrderTraversal(BT->Right);
 66     }
 67 }
 68 
 69 void PostOrderTraversal(BinTree *BT) {
 70     if (BT) {
 71         PostOrderTraversal(BT->Left);
 72         PostOrderTraversal(BT->Right);
 73         Visited(BT);
 74     }
 75 }
 76 
 77 /**
 78  * 遍历二叉树 非递归算法
 79  */
 80 /**
 81  * 前序遍历非递归算法
 82  */
 83 void PreOrderTraversal_Iter(BinTree *BT) {
 84     BinTree *T;
 85     LinkStack * S = InitStack();         /* 生成一个堆栈 */
 86     T = BT;
 87     while (T || !IsStackEmpty(S)) {
 88         while (T) {         /* 一直向左并访问沿途结点后压入堆栈S */
 89             Visited(T);
 90             Push(S, T);
 91             T = T->Left;
 92         }
 93         if (!IsStackEmpty(S)) {
 94             T = Pop(S);         /* 结点弹出堆栈 */
 95             T = T->Right;         /* 转向右子树 */
 96         }
 97     }
 98 }
 99 
100 /**
101  * 中序遍历非递归算法
102  */
103 void InOrderTraversal_Iter(BinTree *BT) {
104     BinTree *T;
105     LinkStack * S = InitStack();         /* 生成一个堆栈 */
106     T = BT;
107     while (T || !IsStackEmpty(S)) {
108         while (T) {         /* 一直向左并将沿途结点后压入堆栈S */
109             Push(S, T);
110             T = T->Left;
111         }
112         if (!IsStackEmpty(S)) {
113             T = Pop(S);         /* 结点弹出堆栈 */
114             Visited(T);
115             T = T->Right;         /* 转向右子树 */
116         }
117     }
118 }
119 
120 /**
121  * 后序遍历非递归算法一
122  * 此思路来源于数据结构教程(李春葆主编)
123  */
124 void PostOrderTraversal_Iter1(BinTree *BT) {
125     if (BT == NULL)
126         return;
127     BinTree *p, *T;
128     LinkStack * S = InitStack();
129     T = BT;
130     int flag = 0;
131     do {
132         while (T) { /*  一直向左并将沿途结点后压入堆栈S */
133             Push(S, T);
134             T = T->Left;
135         }
136         /* 执行到此处,栈顶元素没有做孩子或左子树均已访问过 */
137         flag = 1;             /* 表示 T的左孩子已访问或为空 */
138         p = NULL;             /* p指向栈顶结点的前一个已访问的结点  */
139         while (!IsStackEmpty(S) && flag) {
140             T = getTop(S);             /* 获取当前的栈顶元素,不是删除 */
141             /**
142              * 若p=NULL,表示T的右孩子不存在,而左孩子不存在或已经被访问过,所以访问T;
143              * 若p≠NULL,表示T的右孩子已访问(原因是p指向T的右子树中刚访问过的结点,而p是T的右孩子,
144              *     p一定是T的右子树中后序序列的最后一个结点),所以可以访问T.
145              */
146             if (p == T->Right) {
147                 Visited(T);         /* 访问  */
148                 p = Pop(S);         /* 弹出刚访问的结点并将p指向刚访问的结点 */
149             } else {
150                 T = T->Right;         /* T指向T的右孩子  */
151                 flag = 0;         /* 表示T的右孩子尚未被访问过 */
152             }
153         }
154     } while (!IsStackEmpty(S));
155 
156 }
157 
158 /**
159  * 后序遍历非递归算法二
160  *    思路:要保证根结点在左孩子和右孩子访问之后才能访问,因此对于任一结点p,先将其入栈。
161  *    如果p不存在左孩子和右孩子,则可以直接访问它;
162  *    或者P存在左孩子或者右孩子,但是其左孩子和右孩子都已被访问过了,则同样可以直接访问该结点。
163  *    若非上述两种情况,则将P的右孩子和左孩子依次入栈,这样就保证了每次取栈顶元素的时候,
164  *    左孩子在右孩子前面被访问,左孩子和右孩子都在根结点前面被访问。
165  *    (此思路来源于博客园海子!!!)
166  */
167 void PostOrderTraversal_Iter2(BinTree *BT) {
168     if (!BT)
169         return;
170     BinTree *p, *cur;
171     LinkStack *S = InitStack();
172     p = NULL;
173     cur = NULL;
174     Push(S, BT);
175     while (!IsStackEmpty(S)) {
176         cur = getTop(S);
177         if ((!cur->Left && !cur->Right) /* NULL==cur->Left && NULL==cur->Right */
178         || (p && (p == cur->Left || p == cur->Right))) {
179             Visited(cur);
180             p = Pop(S);
181         } else {
182             if (cur->Right) {
183                 Push(S, cur->Right);
184             }
185             if (cur->Left) {
186                 Push(S, cur->Left);
187             }
188         }
189     }
190 }
191 
192 /**
193  * 层序遍历
194  */
195 void LevelOrderTraversal(BinTree *BT) {
196     BinTree *T;
197     T = BT;
198     if (!T) {
199         return;
200     }
201     Queue *Q = InitQueue();     /* 生成一个队列 */
202     EnQueue(Q, T);         /* 根节点入队 */
203     while (!IsQueueEmpty(Q)) {         /* 队列不为空,弹出一个元素 */
204         T = DeQueue(Q);
205         Visited(T);         /* 访问 */
206         if (T->Left)         /* 左子树不为空入队 */
207             EnQueue(Q, T->Left);
208         if (T->Right)     /* 右子树不为空入队 */
209             EnQueue(Q, T->Right);
210     }
211 }
212 
213 /**
214  * 访问叶子结点的递归算法
215  */
216 void getOrderPrintLeaves(BinTree *BT) {
217     if (BT) {
218         if (!BT->Left && !BT->Right) {
219             Visited(BT);
220         }
221         getOrderPrintLeaves(BT->Left);
222         getOrderPrintLeaves(BT->Right);
223     }
224 }
225 
226 /**
227  * 访问叶子结点的非递归算法
228  */
229 void getOrderPrintLeaves_Iter(BinTree *BT) {
230     BinTree *T;
231     LinkStack *S = InitStack();
232     T = BT;
233     while (T || !IsStackEmpty(S)) {
234         while (T) {
235             Push(S, T);
236             T = T->Left;
237         }
238         if (!IsStackEmpty(S)) {
239             T = Pop(S);
240             if (!T->Left && !T->Right) { /* 当该结点的左子树和右子树都为空,访问 */
241                 Visited(T);
242             }
243             T = T->Right;
244         }
245     }
246 }
247 
248 /**
249  * 求树高
250  */
251 int PostOrderGetHeight(BinTree *BT) {
252     int LH, RH, MaxH;
253     if (BT) {
254         LH = PostOrderGetHeight(BT->Left);
255         RH = PostOrderGetHeight(BT->Right);
256         MaxH = (LH > RH ? LH : RH);
257         return MaxH + 1;
258     }
259     return 0;
260 }
BinTree

 

 

源代码:Test.c

技术分享
 1 #include <stdio.h>
 2 #include <stdlib.h>
 3 #include "header.h"
 4 
 5 extern BinTree *CreateBinTree();
 6 extern void PreOrderTraversal(BinTree *BT);
 7 extern void InOrderTraversal(BinTree *BT);
 8 extern void PreOrderTraversal(BinTree *BT);
 9 extern void InOrderTraversal(BinTree *BT);
10 extern void PostOrderTraversal(BinTree *BT);
11 extern void PreOrderTraversal_Iter(BinTree *BT);
12 extern void InOrderTraversal_Iter(BinTree *BT);
13 extern void PostOrderTraversal_Iter1(BinTree *BT);
14 extern void PostOrderTraversal_Iter2(BinTree *BT);
15 extern void LevelOrderTraversal(BinTree *BT);
16 extern void getOrderPrintLeaves(BinTree *BT);
17 extern void getOrderPrintLeaves_Iter(BinTree *BT);
18 extern int PostOrderGetHeight(BinTree *BT);
19 
20 int main() {
21     puts("START!!!");
22 
23     printf("\n层序序列生成二叉树,请输入层序序列(类型为int,0代表为树的位置为NULL):\n");
24     BinTree * BT = CreateBinTree();
25 
26     printf("PreOrderTraversal: ");
27     PreOrderTraversal(BT);
28     printf("\n");
29 
30     printf("InOrderTraversal: ");
31     InOrderTraversal(BT);
32     printf("\n");
33 
34     printf("PostOrderTraversal: ");
35     PostOrderTraversal(BT);
36     printf("\n");
37 
38     printf("PreOrderTraversal_Iter: ");
39     PreOrderTraversal_Iter(BT);
40     printf("\n");
41 
42     printf("InOrderTraversal_Iter: ");
43     InOrderTraversal_Iter(BT);
44     printf("\n");
45 
46     printf("PostOrderTraversal_Iter1: ");
47     PostOrderTraversal_Iter1(BT);
48     printf("\n");
49 
50     printf("PostOrderTraversal_Iter2:");
51     PostOrderTraversal_Iter2(BT);
52     printf("\n");
53 
54     printf("LevelOrderTraversal: ");
55     LevelOrderTraversal(BT);
56     printf("\n");
57 
58     printf("getOrderPrintLeaves: ");
59     getOrderPrintLeaves(BT);
60     printf("\n");
61 
62     printf("getOrderPrintLeaves_Iter: ");
63     getOrderPrintLeaves_Iter(BT);
64     printf("\n");
65 
66     printf("PostOrderGetHeight: %d",PostOrderGetHeight(BT));
67     printf("\n");
68 
69     puts("END!!!");
70     return EXIT_SUCCESS;
71 }
Test.c

 

 

运行结果:

 技术分享

 

技术分享

 

 技术分享

 

C实现二叉树(模块化集成,遍历的递归与非递归实现)

标签:

原文地址:http://www.cnblogs.com/Vande/p/4632300.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!