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

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

运行结果:

时间: 2024-10-15 21:45:02

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

JAVA递归、非递归遍历二叉树(转)

原文链接: JAVA递归.非递归遍历二叉树 import java.util.Stack; import java.util.HashMap; public class BinTree { private char date; private BinTree lchild; private BinTree rchild; public BinTree(char c) { date = c; } // 先序遍历递归 public static void preOrder(BinTree t) {

Java数据结构系列之——树(4):二叉树的中序遍历的递归与非递归实现

package tree.binarytree; import java.util.Stack; /** * 二叉树的中序遍历:递归与非递归实现 * * @author wl * */ public class BiTreeInOrder { // 中序遍历的递归实现 public static void biTreeInOrderByRecursion(BiTreeNode root) { if (root == null) { return; } biTreeInOrderByRecursi

二叉树遍历递归与非递归实现

说明:本文仅供学习交流,转载请标明出处,欢迎转载! 二叉树遍历是二叉树中非常基础的部分,也是学习二叉树必须熟练掌握的部分,下面我们先给出二叉树三种遍历方式的定义,并通过举例来说明二叉树遍历的过程. 二叉树的遍历分为:前序遍历(也叫先序遍历).中序遍历.后序遍历.所谓前.中.后都是根据当前子树根结点相对左右孩子的位置而言,也就是说: 前序遍历:根结点在前,即:根 ----->左------->右: 中序遍历:根结点在中间,即:左------>根------>右: 后序遍历:根结点在最

二叉树三种遍历(递归以及非递归实现)

package com.shiyeqiang.tree; import java.util.Stack; public class BiTree { public static void main(String[] args) { // 首先构造叶子节点 BiTree leafA1 = new BiTree(4); BiTree leafA2 = new BiTree(5); BiTree leafB1 = new BiTree(6); BiTree leafB2 = new BiTree(7)

二叉树遍历算法总结(递归与非递归)

一:前言 二叉树的遍历方法分四种:前序,中序,后序以及层次遍历. 其中,前中后遍历方法的实现分递归和非递归,非递归遍历的实现需要借助于栈. 实际上,递归的调用就是一种栈的实现,所以,非递归遍历就需要人工借助栈结构来实现. 而层次遍历需要借助队列. 二:前中后序遍历 递归遍历: 递归遍历的思想和方法很简单,通过调整输出语句来实现前,中,后三种遍历. 代码如下: 1 void show(BiTree T) 2 { 3 if(T) 4 { 5 printf("%c ",T->data)

二叉树递归与非递归遍历,最近公共父节点算法

#include <iostream> #include <stack> using namespace std; #define MAX 100 //字符串最大长度 typedef struct Node //二叉树结点 { char data; Node *lchild,*rchild; } *Btree; void createBT(Btree &t); //先序构造二叉树 void preorder(Btree &t); //二叉树递归先序遍历 void i

二叉树的前序、中序、后序遍历(递归、非递归)实现

本文部分来源于CSDN兰亭风雨大牛的原创.链接为http://blog.csdn.net/ns_code/article/details/12977901 二叉树是一种非常重要的数据结构,很多其他数据机构都是基于二叉树的基础演变过来的.二叉树有前.中.后三种遍历方式,因为树的本身就是用递归定义的,因此采用递归的方法实现三种遍历,不仅代码简洁且容易理解,但其开销也比较大,而若采用非递归方法实现三种遍历,则要用栈来模拟实现(递归也是用栈实现的).下面先简要介绍三种遍历方式的递归实现,再详细介绍三种遍

二叉树的存储方式以及递归和非递归的三种遍历方式

树的定义和基本术语 树(Tree)是n(n>=0)个结点的有限集T,T为空时称为空树,否则它满足如下两个条件: (1)有且仅有一个特定的称为根(Root)的结点: (2)其余的结点可分为m(m>=0)个互不相交的子集T1,T2,T3-Tm,其中每个子集又是一棵树,并称其为子树(Subtree). 树形结构应用实例: 1.日常生活:家族谱.行政组织结构:书的目录 2.计算机:资源管理器的文件夹: 编译程序:用树表示源程序的语法结构: 数据库系统:用树组织信息: 分析算法:用树来描述其执行过程:

二叉树的递归和非递归遍历

// 本次练习的是  二叉树的  递归和非递归  遍历   以及二叉树的  节点数  高度  叶子节点数   和查找功能  //如果要是变量在函数栈回归时不回归原值,则可以用引用// #define _CRT_SECURE_NO_WARNINGS 1#include<iostream>#include<stack>#include<queue>using namespace std; template<class T>struct BinaryTreeNod