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