面试常考之二叉树
二叉树在数据结构面试中的地位举足轻重,算得上是大公司面试必问,笔试必考;因为对二叉树的操作直接反应一个人的数据结构功底有多深厚,基础知识是否扎实。。。(一点废话),下面就二叉树的基本操作说一说二叉树的知识点,不对之处还请指正。
面试常考的几个操作:
1:二叉树的基本性质
2:递归建立二叉树
6:求二叉树的深度
7:分层遍历二叉树
9:求二叉树的镜像
10:测试源码
下面就常用的算法给大家讲解这些二叉树的基本性质。
说明:
所有代码使用C语言编写,头信息,常量如下:
1 ** 2 * 树的基本操作tree 3 */ 4 #include <stdio.h> 5 #include <stdlib.h> 6 #include <string.h> 7 8 #define ERROR -1 9 #define OK 1 10 #define OVERFLOW 2 11 #define STACK_INIT_SIZE 100 12 #define STACKINCREMENT 20 13 14 //最大队列长度 15 #define MAXQSIZE 100 16 17 typedef int Struct; 18 typedef char TElement; 19 typedef int Status; 20 int i = 0; //记录树初始化过程,数据的偏移 21 int j = 0; //记录树初始化过程,数据的偏移
二叉树结构体,以及栈、队列的结构体(层次遍历,非递归要用到)如下:
1 //二叉树结构体(二叉链表存储结构) 2 typedef struct BiNode{ 3 TElement data; 4 struct BiNode *lchild,*rchild; 5 }BiTNode, *BiTree; 6 7 //栈表示(用于非递归) 8 typedef struct{ 9 BiTree *base; 10 BiTree *top; 11 int stacksize; 12 }SqStack; 13 14 //使用队列,实现层次遍历 15 typedef struct QNode{ 16 BiTree data; 17 struct QNode *next; 18 }QNode, *QueuePtr; 19 20 typedef struct{ 21 QueuePtr front; 22 QueuePtr rear; 23 }LinkQueue;
一、二叉树第 i 层上最多有2i-1个节点
二、深度为 k 的二叉树,最多有2k - 1个节点
三、对于任意一颗二叉树T,如果其终端节点数为n1度数为2的节点数为n2 则 n1 = n2 + 1;
四、具有n个节点的完全二叉树深度为[ log2n] + 1;
递归常见二叉树,先从左子树开始,arr 是调用传值过去的节点值,i 用于移动数组内的节点值
//创建二叉树 Struct CreateBiTree(BiTree &T, char arr[]){ if(arr[i] == ' '){ i++; T = NULL; }else{ T = (BiTree)malloc(sizeof(BiNode)); if(!T){ exit(ERROR);//分配空间失败; } T->data = arr[i]; i++; CreateBiTree(T->lchild, arr); CreateBiTree(T->rchild, arr); } return OK; }
这是三中常规的遍历二叉树的方法,用的非常多,不仅便于理解,而且三个函数只是调用顺序不同,所以书上页数先给出了这三种遍历。当然在面试中也长问到。
1 //先序遍历(递归方法) 2 int PrintTree(BiTree T){ 3 if(T){ 4 printf("%c ",T->data); 5 PrintTree(T->lchild); 6 PrintTree(T->rchild); 7 8 } 9 return OK; 10 } 11 12 //中序遍历(递归方法) 13 int PrintTreeL(BiTree T){ 14 if(T){ 15 PrintTreeL(T->lchild); 16 printf("%c ",T->data); 17 PrintTreeL(T->rchild); 18 } 19 return OK; 20 } 21 22 //后序遍历(递归方法) 23 int PrintTreeR(BiTree T){ 24 if(T){ 25 PrintTreeR(T->lchild); 26 PrintTreeR(T->rchild); 27 printf("%c ",T->data); 28 } 29 return OK; 30 }
非递归遍历在面试中问的非常多,特别是大公司的面试,几乎是必问,所以这里就非递归的方法每个给出了两种
一、先序遍历:
先序遍历这里给出了两个方法,两种方法都是借助于栈来实现,具体的栈的操作在最后源程序中都有,看家可以看看,非递归的操作比递归麻烦得多,第一种方法是:首先根节点入栈,然后while循环一致判断栈是否为空,第二个while循环一直讲左节点入栈,知道左子树为空。其中PopN(S); 方法是为了将多余的空元素弹出。第二种方法比较推荐开始根节点不入栈,先判断根节点是否为空,这样栈空间中不会有空元素,效率高一点,并且便于理解
1 //先序遍历(非递归方法)(方法1) 2 int PrintTree_Re(BiTree T){ 3 SqStack S; 4 InitStack(S);//建立栈 5 Push(S,T); //树的根节点先入栈 6 BiTree P; 7 while(StackEmpty(S) == 1){ 8 while(GetTop(S,P) && P){ 9 printf("%c ",P->data); 10 Push(S,P->lchild); 11 } 12 PopN(S); 13 if(StackEmpty(S) == 1){ 14 Pop(S,P); 15 Push(S,P->rchild); 16 } 17 } 18 return OK; 19 } 20 21 //先序遍历(非递归方法)(方法2) 22 int PrintTree_Re_T(BiTree T){ 23 SqStack s; 24 InitStack(s); 25 BiTree p; 26 p = T; 27 while(p || StackEmpty(s) == 1){ 28 while(p){ 29 printf("%c ",p->data); 30 Push(s,p); 31 p = p->lchild; 32 } 33 if(StackEmpty(s) == 1){ 34 Pop(s,p); 35 p = p->rchild; 36 } 37 } 38 return OK; 39 }
二、中序遍历:
中序遍历这里也给出2种方法。感觉和先序差不多,只是遍历顺序不同,处理的时候方式一样,这里不再多说。
1 //中序遍历(非递归)(方法1) 2 int PrintTreeL_Re(BiTree T){ 3 SqStack S; 4 InitStack(S);//建立栈 5 Push(S,T); //树的根节点先入栈 6 BiTree P; 7 while(StackEmpty(S) == 1){ 8 while(GetTop(S,P) && P){ 9 Push(S,P->lchild); 10 } 11 PopN(S); 12 if(StackEmpty(S) == 1){ 13 Pop(S,P); 14 printf("%c ",P->data); 15 Push(S,P->rchild); 16 } 17 } 18 return OK; 19 } 20 21 //中序遍历(非递归)(方法2) 22 int PrintTreeL_Re_T(BiTree T){ 23 SqStack S; 24 InitStack(S);//建立栈 25 BiTree P; 26 P = T; 27 while(P || StackEmpty(S) == 1){ 28 if(P){ 29 Push(S,P); 30 P = P->lchild; 31 }else{ 32 Pop(S,P); 33 printf("%c ",P->data); 34 P = P->rchild; 35 } 36 } 37 return OK; 38 }
二、后序遍历:
个人感觉后序遍历的非递归是三种遍历方式中最难的。写了很长时间,总感觉找不到一种合适的方法来保证孩子节点完全遍历。下面来说说这种非递归的遍历。其实会了也比较简单,对于结点P,要保证根结点在左孩子和右孩子访问之后才能访问,先将其入栈。如果P不存在左孩子和右孩子,可以直接访问;或者P 存在左孩子或者右孩子,访问过左孩子和右孩子后可以直接访问该结点。其他情况,则将P的右孩子和左孩子依次入栈。这个就会这一种,应该有其他方法,欢迎指出
1 //后序遍历(非递归方法) 2 int PrintTreeR_Re(BiTree T){ 3 SqStack s; 4 InitStack(s);//建立栈 5 Push(s,T); //树的根节点先入栈 6 BiTree p,q; 7 while(StackEmpty(s) == 1){ 8 GetTop(s,p); 9 if((p->lchild == NULL && p->rchild == NULL) || ( q && ( q == p->lchild || q == p->rchild))){ 10 printf("%c ",p->data); 11 PopN(s); 12 q = p; 13 }else{ 14 if(p->rchild){ 15 Push(s,p->rchild); 16 } 17 if(p->lchild){ 18 Push(s,p->lchild); 19 } 20 } 21 } 22 return OK; 23 }
其实就是遍历一遍二叉树,不再多说,看程序便知
1 //统计二叉树节点的个数 2 void getTreeNodeNum(BiTree T,int &num){ 3 if(!T){ 4 num = 0; 5 } 6 num++; 7 if(T->lchild){ 8 getTreeNodeNum(T->lchild,num); 9 } 10 if(T->rchild){ 11 getTreeNodeNum(T->rchild,num); 12 } 13 }
思想就是从左子树开始遍历,递归完整个树结构,如果二叉树不为空,二叉树的深度 = max(左子树深度, 右子树深度) + 1,参考代码如下:
1 //得到树的深度 2 int getTreeHeight(BiTree T){ 3 int hl,hr,max; 4 if(T!=NULL){ 5 hl=getTreeHeight(T->lchild); 6 hr=getTreeHeight(T->rchild); 7 max=hl>hr?hl:hr; 8 return (max+1); 9 }else{ 10 return 0; 11 } 12 }
一、树的层次结构分层打印与队列的的先进先出相似,所以我选择用队列来完成,首先根节点入队列,然后左孩子,又孩子以此入队列,打印即可
1 /*层次遍历二叉树(借助队列实现)*/ 2 void HierarchicalTree_Q(BiTree T){ 3 LinkQueue Q; 4 InitQueue(Q); //建立队列 5 EnQueue(Q,T); //树的根节点先入列 6 BiTree Ta; 7 while(Q.front != Q.rear){ 8 DeQueue(Q,Ta); 9 if(Ta->lchild){ 10 EnQueue(Q,Ta->lchild); 11 } 12 if(Ta->rchild){ 13 EnQueue(Q,Ta->rchild); 14 } 15 printf("%c ",Ta->data); 16 } 17 }
二、说到分层如果打印树的真实结构应该也可以,所以我想借助堆栈来实现,有兴趣的可以看一下,思想:其实和层次遍历一样,最难的是怎样控制换行先,我的想法是创建一个标志位*,当前行入栈完毕就插入标志位*遍历一个节点就把左孩子和右孩子入栈,以此一层一层的打印,代码检验过,不知道还有没有错误,欢迎指正
1 /*层次遍历二叉树(并且分层打印)(借助栈实现)*/ 2 void HierarchicalTree_DA(BiTree T){ 3 LinkQueue Q; 4 InitQueue(Q);//建立队列 5 EnQueue(Q,T);//树的根节点先入列 6 BiTree Ta1,Tb1,Tc1; 7 8 //创建标志位 9 char data[3] = {'*',' ',' '}; 10 CreateBiTree(Ta1,data); 11 12 //创建移动的指针 13 QueuePtr point; 14 point = Q.front->next;//移动指针先指向头结点 15 EnQueue(Q,Ta1);//插入标志位 16 printf("\n"); 17 while(point){ 18 //判断左右节点 19 if(point->data->lchild || point->data->rchild){ 20 if(point->data->lchild){ 21 EnQueue(Q,point->data->lchild); 22 } 23 if(point->data->rchild){ 24 EnQueue(Q,point->data->rchild); 25 } 26 } 27 point = point->next; //指针下移一位 28 if(point->data->data == '*'){ 29 if(!point->next){//判断是否到结尾(到结尾直接退出) 30 break; 31 } 32 EnQueue(Q,Ta1);//插入标志节点 33 point = point->next; //如果遇到标志位,则指针下移 34 } 35 } 36 37 printf("\n"); 38 //循环输出节点 39 while(Q.front != Q.rear){ 40 DeQueue(Q,Tc1); 41 char str = Tc1->data; 42 if(str == '*'){ 43 printf("\n"); 44 }else{ 45 printf("%c ",str); 46 } 47 } 48 }
利用递归的次数来(孩子节点不为空的条件)来简介得到k层节点的个数,比较简单,代码如下
1 //得到第k层的节点个数 2 int getNodeNum(BiTree T, int k){ 3 if (!T || k < 1){ 4 return 0; 5 } 6 if (k == 1){ 7 return 1; 8 } 9 return getNodeNum(T->lchild, k-1) + getNodeNum(T->rchild, k-1); 10 }
所谓的镜像其实就是左子树和右子树互换颠倒,如下面代码。
1 //写出二叉树的镜像 2 void getNoClone(BiTree &T){ 3 BiTree Ta; 4 if(T){ 5 Ta = T->lchild; 6 T->lchild = T->rchild; 7 T->rchild = Ta; 8 getNoClone(T->lchild); 9 getNoClone(T->rchild); 10 } 11 }
最后附上完整的测试代码,其中包含了,队列的初始化,插入队列,出队列操作,栈的初始化,进栈,出栈,得到栈顶元,树的初始化素等也可以复习一下。中间可定有不对不足的地方,还望大神们多多指正
1 /** 2 * 树的基本操作tree 3 */ 4 #include <stdio.h> 5 #include <stdlib.h> 6 #include <string.h> 7 8 #define ERROR -1 9 #define OK 1 10 #define OVERFLOW 2 11 #define STACK_INIT_SIZE 100 12 #define STACKINCREMENT 20 13 14 //最大队列长度 15 #define MAXQSIZE 100 16 17 typedef int Struct; 18 typedef char TElement; 19 typedef int Status; 20 int i = 0; //记录树初始化过程,数据的偏移 21 int j = 0; //记录树初始化过程,数据的偏移 22 23 24 //二叉树结构体(二叉链表存储结构) 25 typedef struct BiNode{ 26 TElement data; 27 struct BiNode *lchild,*rchild; 28 }BiTNode, *BiTree; 29 30 //栈表示 31 typedef struct{ 32 BiTree *base; 33 BiTree *top; 34 int stacksize; 35 }SqStack; 36 37 //使用队列,实现层次遍历 38 typedef struct QNode{ 39 BiTree data; 40 struct QNode *next; 41 }QNode, *QueuePtr; 42 43 typedef struct{ 44 QueuePtr front; 45 QueuePtr rear; 46 }LinkQueue; 47 48 49 //初始化队列 50 Status InitQueue(LinkQueue &Q){ 51 Q.front = Q.rear = (QueuePtr)malloc(sizeof(BiTree));//动态分配空间 52 if(!Q.front){ 53 exit(ERROR);//分配空间失败 54 } 55 Q.front->next = NULL; 56 return OK; 57 } 58 59 //在队尾插入新元素 60 Status EnQueue(LinkQueue &Q, BiTree e){ 61 QueuePtr p; 62 p = (QueuePtr)malloc(sizeof(BiTree)); 63 if(!p){ 64 exit(ERROR);//分配失败 65 } 66 p->data = e; 67 p->next = NULL; 68 Q.rear->next = p; 69 Q.rear = p; 70 return OK; 71 } 72 73 //删除队头元素,并用e返回 74 void DeQueue(LinkQueue &Q,BiTree &e){ 75 76 if(Q.front != Q.rear){//先判断队列是否为空 77 QueuePtr p; 78 e = Q.front->next->data; 79 if(Q.front->next == Q.rear){//队列只有一个元素 80 p = Q.rear; 81 Q.rear = Q.front; 82 Q.front->next = NULL; 83 }else{ 84 p = Q.front->next; 85 Q.front->next = p->next; 86 p->next = NULL; 87 } 88 //free(p->data); 89 } 90 } 91 92 //创建二叉树 93 Struct CreateBiTree(BiTree &T, char arr[]){ 94 if(arr[i] == ' '){ 95 i++; 96 T = NULL; 97 }else{ 98 T = (BiTree)malloc(sizeof(BiNode)); 99 if(!T){ 100 exit(ERROR);//分配空间失败; 101 } 102 T->data = arr[i]; 103 i++; 104 CreateBiTree(T->lchild, arr); 105 CreateBiTree(T->rchild, arr); 106 } 107 return OK; 108 } 109 110 //先序遍历(递归方法) 111 int PrintTree(BiTree T){ 112 if(T){ 113 printf("%c ",T->data); 114 PrintTree(T->lchild); 115 PrintTree(T->rchild); 116 117 } 118 return OK; 119 } 120 121 //中序遍历(递归方法) 122 int PrintTreeL(BiTree T){ 123 if(T){ 124 PrintTreeL(T->lchild); 125 printf("%c ",T->data); 126 PrintTreeL(T->rchild); 127 } 128 return OK; 129 } 130 131 //后序遍历(递归方法) 132 int PrintTreeR(BiTree T){ 133 if(T){ 134 PrintTreeR(T->lchild); 135 PrintTreeR(T->rchild); 136 printf("%c ",T->data); 137 } 138 return OK; 139 } 140 141 142 //初始化栈 143 Struct InitStack(SqStack &S){ 144 S.base = (BiTree *)malloc(STACK_INIT_SIZE * sizeof(BiTree)); 145 S.top = S.base; 146 if(!S.base){ 147 exit(ERROR);//分配失败 148 } 149 S.stacksize = STACK_INIT_SIZE; 150 return OK; 151 } 152 153 //push入栈操作 154 Struct Push(SqStack &S, BiTree T){ 155 if(S.top - S.base >= S.stacksize){ 156 S.base = (BiTree *)realloc(S.base,(S.stacksize + STACKINCREMENT) * sizeof(BiTree)); 157 if(!S.base){ 158 exit(ERROR); 159 } 160 S.top = S.base + S.stacksize; 161 S.stacksize += STACKINCREMENT; 162 } 163 *S.top = T; 164 S.top++; 165 166 return OK; 167 } 168 169 //出栈操作 170 Struct Pop(SqStack &S,BiTree &P){ 171 if(S.base != S.top){ 172 P = *(--S.top); 173 } 174 return OK; 175 } 176 177 //出栈操作 178 Struct PopN(SqStack &S){ 179 if(S.base != S.top){ 180 --S.top; 181 } 182 return OK; 183 } 184 185 //得到栈顶元素操作 186 Struct GetTop(SqStack S,BiTree &P){ 187 if(S.base != S.top){ 188 P = *(S.top - 1); 189 } 190 return OK; 191 } 192 193 //判断是否是空栈 194 int StackEmpty(SqStack S){ 195 if(S.base != S.top){ 196 return 1; 197 }else{ 198 return 0; 199 } 200 } 201 202 //返回栈长度 203 int GetLength(SqStack S){ 204 return S.top - S.base; 205 } 206 207 //先序遍历(非递归方法)(方法1) 208 int PrintTree_Re(BiTree T){ 209 SqStack S; 210 InitStack(S);//建立栈 211 Push(S,T); //树的根节点先入栈 212 BiTree P; 213 while(StackEmpty(S) == 1){ 214 while(GetTop(S,P) && P){ 215 printf("%c ",P->data); 216 Push(S,P->lchild); 217 } 218 PopN(S); 219 if(StackEmpty(S) == 1){ 220 Pop(S,P); 221 Push(S,P->rchild); 222 } 223 } 224 return OK; 225 } 226 227 //先序遍历(非递归方法)(方法2) 228 int PrintTree_Re_T(BiTree T){ 229 SqStack s; 230 InitStack(s); 231 BiTree p; 232 p = T; 233 while(p || StackEmpty(s) == 1){ 234 while(p){ 235 printf("%c ",p->data); 236 Push(s,p); 237 p = p->lchild; 238 } 239 if(StackEmpty(s) == 1){ 240 Pop(s,p); 241 p = p->rchild; 242 } 243 } 244 return OK; 245 } 246 247 //中序遍历(非递归)(方法1) 248 int PrintTreeL_Re(BiTree T){ 249 SqStack S; 250 InitStack(S);//建立栈 251 Push(S,T); //树的根节点先入栈 252 BiTree P; 253 while(StackEmpty(S) == 1){ 254 while(GetTop(S,P) && P){ 255 Push(S,P->lchild); 256 } 257 PopN(S); 258 if(StackEmpty(S) == 1){ 259 Pop(S,P); 260 printf("%c ",P->data); 261 Push(S,P->rchild); 262 } 263 } 264 return OK; 265 } 266 267 //中序遍历(非递归)(方法2) 268 int PrintTreeL_Re_T(BiTree T){ 269 SqStack S; 270 InitStack(S);//建立栈 271 BiTree P; 272 P = T; 273 while(P || StackEmpty(S) == 1){ 274 if(P){ 275 Push(S,P); 276 P = P->lchild; 277 }else{ 278 Pop(S,P); 279 printf("%c ",P->data); 280 P = P->rchild; 281 } 282 } 283 return OK; 284 } 285 286 //后序遍历(非递归方法) 287 int PrintTreeR_Re(BiTree T){ 288 SqStack s; 289 InitStack(s);//建立栈 290 Push(s,T); //树的根节点先入栈 291 BiTree p,q; 292 while(StackEmpty(s) == 1){ 293 GetTop(s,p); 294 if((p->lchild == NULL && p->rchild == NULL) || ( q && ( q == p->lchild || q == p->rchild))){ 295 printf("%c ",p->data); 296 PopN(s); 297 q = p; 298 }else{ 299 if(p->rchild){ 300 Push(s,p->rchild); 301 } 302 if(p->lchild){ 303 Push(s,p->lchild); 304 } 305 } 306 } 307 return OK; 308 } 309 310 311 /*层次遍历二叉树*/ 312 void HierarchicalTree(BiTree T){ 313 BiTree Ta = T; 314 if(Ta){ 315 printf("%c ",Ta->data); 316 if(Ta->lchild){ 317 //printf("%c ",Ta->lchild->data); 318 HierarchicalTree(Ta->lchild); 319 } 320 if(Ta->rchild){ 321 //printf("%c ",Ta->rchild->data); 322 HierarchicalTree(Ta->rchild); 323 } 324 } 325 } 326 327 /*层次遍历二叉树(借助队列实现)*/ 328 void HierarchicalTree_Q(BiTree T){ 329 LinkQueue Q; 330 InitQueue(Q); //建立队列 331 EnQueue(Q,T); //树的根节点先入列 332 BiTree Ta; 333 while(Q.front != Q.rear){ 334 DeQueue(Q,Ta); 335 if(Ta->lchild){ 336 EnQueue(Q,Ta->lchild); 337 } 338 if(Ta->rchild){ 339 EnQueue(Q,Ta->rchild); 340 } 341 printf("%c ",Ta->data); 342 } 343 } 344 345 /*层次遍历二叉树(并且分层打印)(借助队列实现)*/ 346 void HierarchicalTree_DA(BiTree T){ 347 LinkQueue Q; 348 InitQueue(Q);//建立队列 349 EnQueue(Q,T);//树的根节点先入列 350 BiTree Ta1,Tb1,Tc1; 351 352 //创建标志位 353 char data[3] = {'*',' ',' '}; 354 CreateBiTree(Ta1,data); 355 356 //创建移动的指针 357 QueuePtr point; 358 point = Q.front->next;//移动指针先指向头结点 359 EnQueue(Q,Ta1);//插入标志位 360 printf("\n"); 361 while(point){ 362 //判断左右节点 363 if(point->data->lchild || point->data->rchild){ 364 if(point->data->lchild){ 365 EnQueue(Q,point->data->lchild); 366 } 367 if(point->data->rchild){ 368 EnQueue(Q,point->data->rchild); 369 } 370 } 371 point = point->next; //指针下移一位 372 if(point->data->data == '*'){ 373 if(!point->next){//判断是否到结尾(到结尾直接退出) 374 break; 375 } 376 EnQueue(Q,Ta1);//插入标志节点 377 point = point->next; //如果遇到标志位,则指针下移 378 } 379 } 380 381 printf("\n"); 382 //循环输出节点 383 while(Q.front != Q.rear){ 384 DeQueue(Q,Tc1); 385 char str = Tc1->data; 386 if(str == '*'){ 387 printf("\n"); 388 }else{ 389 printf("%c ",str); 390 } 391 } 392 } 393 394 //统计二叉树节点的个数 395 void getTreeNodeNum(BiTree T,int &num){ 396 if(!T){ 397 num = 0; 398 } 399 num++; 400 if(T->lchild){ 401 getTreeNodeNum(T->lchild,num); 402 } 403 if(T->rchild){ 404 getTreeNodeNum(T->rchild,num); 405 } 406 } 407 408 //得到树的深度 409 int getTreeHeight(BiTree T){ 410 int hl,hr,max; 411 if(T!=NULL){ 412 hl=getTreeHeight(T->lchild); 413 hr=getTreeHeight(T->rchild); 414 max=hl>hr?hl:hr; 415 return (max+1); 416 }else{ 417 return 0; 418 } 419 } 420 421 //得到第k层的节点个数 422 int getNodeNum(BiTree T, int k){ 423 if (!T || k < 1){ 424 return 0; 425 } 426 if (k == 1){ 427 return 1; 428 } 429 return getNodeNum(T->lchild, k-1) + getNodeNum(T->rchild, k-1); 430 } 431 432 void main(){ 433 i = 0; 434 //char Data[15] = {'A','B','C',' ',' ','D','E',' ','G',' ',' ','F',' ',' ',' '}; 435 //char Data[15] = {'A','B','C',' ',' ','D','E',' ',' ','G',' ',' ','F',' ',' '}; 436 char Data[16] = {'A','B','C',' ',' ',' ','D','E',' ','G',' ',' ','F',' ',' ',' '}; 437 //char Data[7] = {'A','B','C',' ',' ',' ',' '}; 438 //char Data[7] = {'A',' ','b',' ','c',' ',' '}; 439 BiTree Ta,Tb; 440 CreateBiTree(Ta,Data); 441 printf("*****************递归方法遍历二叉树**************\n"); 442 printf("先序遍历:"); 443 PrintTree(Ta); 444 445 printf("\n"); 446 printf("中序遍历:"); 447 PrintTreeL(Ta); 448 449 printf("\n"); 450 printf("后序遍历:"); 451 PrintTreeR(Ta); 452 printf("\n"); 453 454 printf("非递归先序遍历法1:"); 455 PrintTree_Re(Ta); 456 printf("\n"); 457 458 printf("非递归先序遍历法2:"); 459 PrintTree_Re_T(Ta); 460 printf("\n"); 461 462 printf("非递归中序遍历法1:"); 463 PrintTreeL_Re(Ta); 464 printf("\n"); 465 466 printf("非递归中序遍历法2:"); 467 PrintTreeL_Re_T(Ta); 468 printf("\n"); 469 470 printf("非递归后序遍历:"); 471 PrintTreeR_Re(Ta); 472 printf("\n"); 473 474 printf("层次遍历:"); 475 HierarchicalTree_Q(Ta); 476 printf("\n"); 477 478 printf("\n"); 479 printf("层次遍历(分层显示):"); 480 i = 0; 481 HierarchicalTree_DA(Ta); 482 printf("\n"); 483 484 printf("总结点个数:"); 485 int TreeNum = 0; 486 getTreeNodeNum(Ta,TreeNum); 487 printf("%d ",TreeNum); 488 printf("\n"); 489 490 printf("树的深度:"); 491 int TreeHeight = 0; 492 TreeHeight = getTreeHeight(Ta); 493 printf("%d ",TreeHeight); 494 printf("\n"); 495 496 printf("得到第3层的节点个数:"); 497 printf("%d",getNodeNum(Ta,3)); 498 printf("\n"); 499 500 }
运行结果:
转载请注明出处,谢谢!