数据结构(13)二叉树的动态链表存储和遍历的实现

来源:互联网 发布:rpc java 框架 编辑:程序博客网 时间:2024/05/22 04:45

http://blog.csdn.net/u010366748/article/details/50765512



参考书籍:数据结构(C语言版)严蔚敏吴伟民编著清华大学出版社

1.动态二叉链表存储即遍历的实现

1.1.动态二叉链表的定义

[cpp] view plain copy
  1. #include<stdio.h>  
  2. #include<stdlib.h>  
  3. #define NULL 0  
  4. typedef char TElemType;  
  5. //动态二叉链表  
  6. typedef struct BiTNode{  
  7.     TElemType data;  
  8.     struct BiTNode *lchild, *rchild;  
  9. }BiTNode, *BiTree;  

测试用例:


测试按先序序列输入:abc..de.g..f...#,点号代表空树,#为输入结束符

另外下面的算法有使用到栈的,栈的相关实现如下:

[cpp] view plain copy
  1. #define MAXSIZE 100  
  2. typedef BiTNode* SElemType;  
  3. typedef struct SqStack{  
  4.     SElemType data[MAXSIZE];  
  5.     int top;//指向栈顶元素  
  6. }SqStack;  
  7.   
  8. //初始化空栈  
  9. void initStack(SqStack &s){  
  10.     s.top = 0;  
  11. }  
  12.   
  13. //判栈空  
  14. bool isEmpty(SqStack s){  
  15.     if(s.top == 0){  
  16.         //printf("是空栈\n");//  
  17.         return true;  
  18.     }else{  
  19.         return false;  
  20.     }  
  21. }  
  22.   
  23. //判栈满  
  24. bool isFull(SqStack s){  
  25.     if(s.top == MAXSIZE){  
  26.         return true;  
  27.     }  
  28.     else{  
  29.         return false;  
  30.     }  
  31. }  
  32.   
  33. //取栈顶元素  
  34. void getTopElem(SqStack s, SElemType &e){  
  35.     if(!isEmpty(s))  
  36.         e = s.data[s.top-1];  
  37.     else  
  38.         printf("此栈为空栈,取栈顶元素失败\n");  
  39. }  
  40.   
  41. //入栈  
  42. void push(SqStack &s, SElemType e){  
  43.     if(!isFull(s)){  
  44.         s.data[s.top] = e;  
  45.         s.top++;  
  46.     }else  
  47.         printf("此栈已满,入栈操作失败\n");  
  48. }  
  49.   
  50. //出栈  
  51. void pop(SqStack &s, SElemType &e){  
  52.     if(!isEmpty(s)){  
  53.         e = s.data[s.top-1];  
  54.         s.top--;  
  55.     }  
  56.     else  
  57.         printf("此栈为空栈,出栈操作失败\n");  
  58. }  
更详细的栈实现请参见我的另一篇博文:数据结构(5)--栈的定义以及相关操作的实现http://blog.csdn.net/u010366748/article/details/50639195

1.2按先序序列输入创建二叉树的递归算法

[cpp] view plain copy
  1. //利用先序序列建立一颗二叉树,先序序列读入:'a', 'b', 'c', '.', '.', 'd', 'e', '.', 'g', '.', '.', 'f', '.', '.', '.'   
  2. //,'.'代表空树  
  3. //测试用例:abc..de.g..f...#  
  4. void createBiTreeByPreOrder(BiTree &T){  
  5.     //按先序次序输入二叉树中节点的值(一个字符),点号字符表示空树,构造二叉链表表示的二叉树  
  6.     //注意:若输入的字符数(不含#号)为n个,则相应的空树即点号就应该有n+1个  
  7.     char ch;  
  8.     scanf("%c", &ch);  
  9.     //printf("test:%c\n", ch);  
  10.     if(ch != '#'){  
  11.         if(ch == '.'){  
  12.             T = NULL;  
  13.         }else{  
  14.             T = (BiTNode *)malloc(sizeof(BiTNode));  
  15.             T->data = ch;  
  16.             createBiTreeByPreOrder(T->lchild);  
  17.             createBiTreeByPreOrder(T->rchild);  
  18.         }  
  19.     }  
  20. }  

1.3先序遍历二叉树的递归算法

[cpp] view plain copy
  1. //先序遍历打印二叉树的递归算法(根、左、右)  
  2. void preOrderPrint(BiTree T){  
  3.     if(T){  
  4.         printf("%c ", T->data);  
  5.         preOrderPrint(T->lchild);  
  6.         preOrderPrint(T->rchild);  
  7.     }  
  8. }  

1.4先序遍历二叉树的非递归算法

[cpp] view plain copy
  1. //先序遍历打印二叉树的非递归算法(根、左、右)  
  2. void preOrderPrint2(BiTree T){  
  3.     SqStack s;  
  4.     initStack(s);  
  5.     BiTNode *p = T;   
  6.     while(p || !isEmpty(s)){          
  7.         if(p){  
  8.             printf("%c ", p->data);  
  9.             push(s, p);  
  10.             p = p->lchild;  
  11.         }else{  
  12.             //printStack(s);  
  13.             pop(s, p);//栈顶指针(当前层的根节点指针)弹出  
  14.             p = p->rchild;  
  15.         }  
  16.     }  
  17. }  
演示:

[cpp] view plain copy
  1. void main(){  
  2.     BiTree T;  
  3.     printf("请按先序次序输入二叉树各节点的值,以空格表示空树,以#号结束:\n");  
  4.     createBiTreeByPreOrder(T);  
  5.   
  6.     printf("先序遍历打印二叉树:\n");  
  7.     preOrderPrint(T);  
  8.     printf("\n");  
  9.       
  10.     printf("先序遍历打印二叉树(非递归算法):\n");  
  11.     preOrderPrint2(T);  
  12.     printf("\n");  
  13. }  


1.5中序遍历二叉树的递归算法

[cpp] view plain copy
  1. //中序遍历打印二叉树的递归算法(左、根、右)  
  2. void inOrderPrint(BiTree T){  
  3.     if(T){  
  4.         inOrderPrint(T->lchild);  
  5.         printf("%c ", T->data);        
  6.         inOrderPrint(T->rchild);  
  7.     }  
  8. }  

1.6中序遍历二叉树的非递归算法

[cpp] view plain copy
  1. //中序遍历打印二叉树的非递归算法(左、根、右)  
  2. void inOrderPrint2(BiTree T){  
  3.     SqStack s;  
  4.     initStack(s);  
  5.     BiTNode *p = T;   
  6.     while(p || !isEmpty(s)){  
  7.         if(p){  
  8.             push(s, p);  
  9.             p = p->lchild;  
  10.         }else{  
  11.             pop(s, p);//栈顶指针(当前层的根节点指针)弹出  
  12.             printf("%c ", p->data);            
  13.             p = p->rchild;  
  14.         }  
  15.     }  
  16. }  
演示:

[cpp] view plain copy
  1. void main(){  
  2.     BiTree T;  
  3.     printf("请按先序次序输入二叉树各节点的值,以空格表示空树,以#号结束:\n");  
  4.     createBiTreeByPreOrder(T);  
  5.   
  6.     printf("中序遍历打印二叉树:\n");  
  7.     inOrderPrint(T);  
  8.     printf("\n");  
  9.       
  10.     printf("中序遍历打印二叉树(非递归算法):\n");  
  11.     inOrderPrint2(T);  
  12.     printf("\n");  
  13. }  


1.7后序遍历二叉树的递归算法

[cpp] view plain copy
  1. //后序遍历打印二叉树的递归算法(左、右、根)  
  2. void postOrderPrint(BiTree T){  
  3.     if(T){  
  4.         postOrderPrint(T->lchild);  
  5.         postOrderPrint(T->rchild);  
  6.         printf("%c ", T->data);  
  7.     }  
  8. }  

1.8后序遍历二叉树的非递归算法

[cpp] view plain copy
  1. //后序遍历打印二叉树的非递归算法(左、右、根)  
  2. void postOrderPrint2(BiTree T){  
  3.     SqStack s;  
  4.     initStack(s);  
  5.     BiTNode *p = T;  
  6.     while(p || !isEmpty(s)){  
  7.         if(p){  
  8.             push(s, p);  
  9.             p = p->lchild;  
  10.         }else{   
  11.             BiTNode *top;  
  12.             getTopElem(s, top);//取得栈顶元素  
  13.             if(top->data > 0){//栈顶元素的右子树还没有被访问过  
  14.                 p = top->rchild;  
  15.                 top->data = -top->data;//赋右子树已遍历标志  
  16.                   
  17.             }else{//栈顶元素的右子树已经访问过了  
  18.                 printf("%c ", -top->data);  
  19.                 pop(s, top);  
  20.                 //p = NULL;               
  21.             }  
  22.         }         
  23.     }  
  24. }  
演示:

[cpp] view plain copy
  1. void main(){  
  2.     BiTree T;  
  3.     printf("请按先序次序输入二叉树各节点的值,以空格表示空树,以#号结束:\n");  
  4.     createBiTreeByPreOrder(T);  
  5.   
  6.     printf("后序遍历打印二叉树:\n");  
  7.     postOrderPrint(T);  
  8.     printf("\n");  
  9.   
  10.     printf("后序遍历打印二叉树(非递归算法):\n");  
  11.     postOrderPrint2(T);  
  12.     printf("\n");  
  13. }  


1.9按层次遍历二叉树的非递归算法

[cpp] view plain copy
  1. typedef BiTNode* QElemType;  
  2. typedef struct{  
  3.     QElemType data[20];  
  4.     int f;//指向队头元素  
  5.     int r;//指向对尾元素的下一个位置  
  6. }SqQueue;  
  7. //初始化一个空队列  
  8. void initQueue(SqQueue &Q){  
  9.     Q.f = Q.r = 0;  
  10. }  
  11.   
  12. //按层次遍历(从上到下,从左到右),  
  13. void hierarchicalTraversePrint(BiTree T){  
  14.     //QElemType queue[20];//维护一个顺序队列,用来按层次存放每个实节点,实际上是一个广度优先搜索  
  15.     //int f = 0, r = 0;//队头队尾  
  16.     SqQueue Q;//维护一个顺序队列,用来按层次存放每个实节点,实际上是一个广度优先搜索  
  17.     initQueue(Q);  
  18.     //注意,不能写成int f, r = 0;否则f没有被赋值  
  19.     if(T){  
  20.         //queue[0] = T;//根节点入队  
  21.         Q.data[Q.r] = T;//根节点入队  
  22.         Q.r++;  
  23.     }  
  24.     while(Q.f != Q.r){  
  25.         //先将队头元素的左孩子依次入队  
  26.         if(Q.data[Q.f]->lchild){  
  27.             Q.data[Q.r] = Q.data[Q.f]->lchild;  
  28.             Q.r++;  
  29.         }  
  30.         //将队头元素的右孩子依次入队  
  31.         if(Q.data[Q.f]->rchild){  
  32.             Q.data[Q.r] = Q.data[Q.f]->rchild;  
  33.             Q.r++;  
  34.         }  
  35.         //然后打印(访问)队头元素,并将队头元素出队       
  36.         printf("%c ", Q.data[Q.f]->data);  
  37.         Q.f++;//队头元素出队  
  38.     }  
  39.     printf("\n");  
  40. }  
演示:

[cpp] view plain copy
  1. void main(){  
  2.     BiTree T;  
  3.     printf("请按先序次序输入二叉树各节点的值,以空格表示空树,以#号结束:\n");  
  4.     createBiTreeByPreOrder(T);  
  5.   
  6.     printf("按层次遍历打印二叉树(非递归算法):\n");  
  7.     hierarchicalTraversePrint(T);  
  8. }  


2.遍历二叉树的应用

2.1求二叉树的深度

[cpp] view plain copy
  1. //求二叉树的深度  
  2. int getBiTreeDepth(BiTree T){  
  3.     if(!T){  
  4.         return 0;  
  5.     }  
  6.     int leftTreeDepth = getBiTreeDepth(T->lchild);  
  7.     int rightTreeDepth = getBiTreeDepth(T->rchild);  
  8.     return leftTreeDepth > rightTreeDepth ? (leftTreeDepth+1) : (rightTreeDepth+1);  
  9. }  
演示:

[cpp] view plain copy
  1. void main(){  
  2.     BiTree T;  
  3.     printf("请按先序次序输入二叉树各节点的值,以空格表示空树,以#号结束:\n");  
  4.     createBiTreeByPreOrder(T);  
  5.   
  6.     int depth = getBiTreeDepth(T);  
  7.     printf("该二叉树树的深度为%d\n", depth);  
  8. }  


2.2求二叉树的结点数

[cpp] view plain copy
  1. //求二叉树的节点数  
  2. int getBiTreeSize(BiTree T){  
  3.     if(!T)  
  4.         return 0;  
  5.     int leftTreeSize = getBiTreeSize(T->lchild);  
  6.     int rightTreeSize = getBiTreeSize(T->rchild);  
  7.     return leftTreeSize + rightTreeSize + 1;  
  8. }  
演示:

[cpp] view plain copy
  1. void main(){  
  2.     BiTree T;  
  3.     printf("请按先序次序输入二叉树各节点的值,以空格表示空树,以#号结束:\n");  
  4.     createBiTreeByPreOrder(T);  
  5.   
  6.     int size = getBiTreeSize(T);  
  7.     printf("该二叉树树的结点数为%d\n", size);  
  8. }  


2.3求二叉树的叶子节点数

[cpp] view plain copy
  1. //先序遍历求叶子节点数  
  2. int getBiTreeLeafNodesNum2(BiTree T){  
  3.     if(T){  
  4.         if(!T->lchild && !T->rchild)  
  5.             return 1;  
  6.         else{  
  7.             int leftTreeLeafNodesNum = getBiTreeLeafNodesNum2(T->lchild);  
  8.             int rightTreeLeafNodesNum = getBiTreeLeafNodesNum2(T->rchild);  
  9.             return leftTreeLeafNodesNum + rightTreeLeafNodesNum;  
  10.         }  
  11.     }else{  
  12.         return 0;  
  13.     }  
  14. }  

或者:

[cpp] view plain copy
  1. //先序遍历求叶子节点数  
  2. void getBiTreeLeafNodesNum(BiTree T, int &count){  
  3.     if(T){  
  4.         if(!T->lchild && !T->rchild)  
  5.             count++;  
  6.         //else{  
  7.             getBiTreeLeafNodesNum(T->lchild, count);  
  8.             getBiTreeLeafNodesNum(T->rchild, count);  
  9.         //}  
  10.     }  
  11. }  
演示:

[cpp] view plain copy
  1. void main(){  
  2.     BiTree T;  
  3.     printf("请按先序次序输入二叉树各节点的值,以空格表示空树,以#号结束:\n");  
  4.     createBiTreeByPreOrder(T);  
  5.   
  6.     int leafNodesNum2 = 0;  
  7.     leafNodesNum2 = getBiTreeLeafNodesNum2(T);  
  8.     printf("该二叉树树的叶子点数为%d\n", leafNodesNum2);  
  9. }  
或者:

[cpp] view plain copy
  1. void main(){  
  2.     BiTree T;  
  3.     printf("请按先序次序输入二叉树各节点的值,以空格表示空树,以#号结束:\n");  
  4.     createBiTreeByPreOrder(T);  
  5.   
  6.     int leafNodesNum = 0;  
  7.     getBiTreeLeafNodesNum(T, leafNodesNum);  
  8.     printf("该二叉树树的叶子点数为%d\n", leafNodesNum);  
  9. }  

阅读全文
0 0
原创粉丝点击