二叉树的基本操作


二叉树作为一种非常重要的数据结构,今天对其做简单的回顾
1、二叉树的定义

[cpp]  view plain  copy
  1. typedef char ElementType;  
  2.   
  3. typedef struct BiTreeNode  
  4. {  
  5.     ElementType data;  
  6.     struct BiTreeNode* lchild;  
  7.     struct BiTreeNode* rchild;  
  8. }BiTreeNode, *BiTree;  
2、 二叉树的建立和销毁

(1)利用先序序列递归建立二叉树

[cpp]  view plain  copy
  1. //递归的建立一棵二叉树   
  2. //输入为二叉树的先序序列   
  3. void createBiTree(BiTree &T)  
  4. {  
  5.     char data;  
  6.     data = getchar();  
  7.     if(data == '#')  
  8.     {  
  9.         T = NULL;  
  10.     }  
  11.     else  
  12.     {  
  13.         T = new BiTreeNode;  
  14.         T->data = data;  
  15.         createBiTree(T->lchild);  
  16.         createBiTree(T->rchild);  
  17.     }  
  18. }  

(2)利用广义表建立二叉树

[cpp]  view plain  copy
  1. //通过广义表建立二叉树   
  2. void createBiTreeWithGenList(BiTree &T)  
  3. {  
  4.     stack<BiTree> s;//存放待输入孩子的结点   
  5.     BiTree p = NULL;//用于生成新的结点  
  6.     int k = 0;//记录期待的结点, k==1表示期待左孩子结点,k==2期待右孩子结点  
  7.     char ch = getchar();  
  8.       
  9.     //处理根结点   
  10.     if(ch!='#')  
  11.     {  
  12.         p = new BiTreeNode;  
  13.         p->data = ch;  
  14.         p->lchild = NULL;  
  15.         p->rchild = NULL;  
  16.         T = p;//根结点   
  17.     }  
  18.     while((ch=getchar())!='#')  
  19.     {  
  20.         switch(ch)  
  21.         {  
  22.             case '(':  
  23.                 s.push(p);//上一个生成的结点,即p入栈,p有孩子   
  24.                 k = 1;  //下一个插入的应为左孩子结点   
  25.                 break;  
  26.             case ',':  
  27.                 k = 2;  //下一个插入的应为右孩子结点   
  28.                 break;  
  29.             case ')':  
  30.                 s.pop();//结点完成孩子的输入,出栈   
  31.                 break;  
  32.             default:  
  33.                 p = new BiTreeNode;  
  34.                 p->data = ch;  
  35.                 p->lchild = NULL;  
  36.                 p->rchild = NULL;  
  37.                 if(k==1)  
  38.                     s.top()->lchild = p;  
  39.                 else   
  40.                     s.top()->rchild = p;  
  41.         }         
  42.     }  
  43. }  

(3)输出二叉树的广义表表示

[cpp]  view plain  copy
  1. //以广义表的方式输出二叉树  
  2. void printBiTreeWithGenList(const BiTree&T)  
  3. {  
  4.     if(T)  
  5.     {  
  6.         cout<<T->data;  
  7.         if(T->lchild ||T->rchild)//左右子树不全空   
  8.         {  
  9.             cout<<"(";  
  10.             printBiTreeWithGenList(T->lchild);//递归输出左子树 ,可能为空   
  11.             if(T->rchild)          
  12.             {  
  13.                 cout<<",";  
  14.                 printBiTreeWithGenList(T->rchild);  
  15.             }  
  16.             cout<<")";  
  17.         }  
  18.     }  
  19. }  

(4)二叉树的销毁

[cpp]  view plain  copy
  1. //递归销毁一棵二叉树  
  2. void destroyBiTree(BiTree &T)  
  3. {  
  4.     if(T)  
  5.     {  
  6.         destroyBiTree(T->lchild);  
  7.         destroyBiTree(T->rchild);  
  8.         delete T;  
  9.         T = NULL;  
  10.     }  
  11. }  
3 、二叉树的递归遍历

(1)先序递归遍历

[cpp]  view plain  copy
  1. //递归先序遍历二叉树   
  2. void preOrderTraverse(const BiTree &T)  
  3. {  
  4.     if(T)  
  5.     {  
  6.         cout<<T->data<<" ";//输出根节点值   
  7.         preOrderTraverse(T->lchild);//遍历左子树   
  8.         preOrderTraverse(T->rchild);//遍历右子树   
  9.     }  
  10. }  

(2)中序递归遍历

[cpp]  view plain  copy
  1. //递归中序遍历二叉树  
  2. void inOrderTraverse(const BiTree &T)  
  3. {  
  4.     if(T)  
  5.     {  
  6.         inOrderTraverse(T->lchild);//遍历左子树   
  7.         cout<<T->data<<" ";//输出根节点值   
  8.         inOrderTraverse(T->rchild);//遍历右子树   
  9.     }  
  10. }  

(3)后序递归遍历

[cpp]  view plain  copy
  1. //递归后序遍历二叉树  
  2. void postOrderTraverse(const BiTree &T)  
  3. {  
  4.     if(T)  
  5.     {  
  6.         postOrderTraverse(T->lchild);//遍历左子树   
  7.         postOrderTraverse(T->rchild);//遍历右子树   
  8.         cout<<T->data<<" ";//输出根节点值   
  9.     }   
  10. }  

4 、二叉树的其他常见递归算法

(1)递归求树的深度(高度)

[cpp]  view plain  copy
  1. //递归求树的深度   
  2. int depthOfBiTree(const BiTree &T)  
  3. {  
  4.     int ldepth;  
  5.     int rdepth;  
  6.       
  7.     if(T==NULL)//空树   
  8.         return 0;  
  9.     ldepth = depthOfBiTree(T->lchild);  
  10.     rdepth = depthOfBiTree(T->rchild);  
  11.       
  12.     return (ldepth>rdepth)?(ldepth+1):(rdepth+1);  
  13. }  

(2)递归求树的叶子结点个数

[cpp]  view plain  copy
  1. //递归求二叉树的叶子结点个数  
  2. int leafCountOfBiTree(const BiTree &T)  
  3. {     
  4.     if(T==NULL)  
  5.         return 0;  
  6.     if(T->lchild==NULL && T->rchild==NULL)  
  7.         return 1;  
  8.     return leafCountOfBiTree(T->lchild) + leafCountOfBiTree(T->rchild);  
  9. }  
(3)递归交换左右子女
[cpp]  view plain  copy
  1. //交换二叉树的左右子女  
  2. void exchangeChild(BiTree &T)  
  3. {  
  4.     if(T)  
  5.     {  
  6.         BiTree temp = NULL;  
  7.           
  8.         if(T->lchild ||T->rchild)  
  9.         {  
  10.             temp = T->lchild;  
  11.             T->lchild = T->rchild;  
  12.             T->rchild = temp;  
  13.             exchangeChild(T->lchild);  
  14.             exchangeChild(T->rchild);  
  15.         }  
  16.     }  
  17. }  

5、完整的测试代码

[cpp]  view plain  copy
  1. #include <cstdlib>  
  2. #include <iostream>  
  3. #include <stack>  
  4.   
  5. using namespace std;  
  6.   
  7. //二叉树定义   
  8. typedef char ElementType;  
  9.   
  10. typedef struct BiTreeNode  
  11. {  
  12.     ElementType data;  
  13.     struct BiTreeNode* lchild;  
  14.     struct BiTreeNode* rchild;  
  15. }BiTreeNode, *BiTree;  
  16.   
  17.   
  18. //递归的建立一棵二叉树   
  19. //输入为二叉树的先序序列   
  20. void createBiTree(BiTree &T)  
  21. {  
  22.     char data;  
  23.     data = getchar();  
  24.     if(data == '#')  
  25.     {  
  26.         T = NULL;  
  27.     }  
  28.     else  
  29.     {  
  30.         T = new BiTreeNode;  
  31.         T->data = data;  
  32.         createBiTree(T->lchild);  
  33.         createBiTree(T->rchild);  
  34.     }  
  35. }  
  36.   
  37. //通过广义表建立二叉树   
  38. void createBiTreeWithGenList(BiTree &T)  
  39. {  
  40.     stack<BiTree> s;//存放待输入孩子的结点   
  41.     BiTree p = NULL;//用于生成新的结点  
  42.     int k = 0;//记录期待的结点, k==1表示期待左孩子结点,k==2期待右孩子结点  
  43.     char ch = getchar();  
  44.       
  45.     //处理根结点   
  46.     if(ch!='#')  
  47.     {  
  48.         p = new BiTreeNode;  
  49.         p->data = ch;  
  50.         p->lchild = NULL;  
  51.         p->rchild = NULL;  
  52.         T = p;//根结点   
  53.     }  
  54.     while((ch=getchar())!='#')  
  55.     {  
  56.         switch(ch)  
  57.         {  
  58.             case '(':  
  59.                 s.push(p);//上一个生成的结点,即p入栈,p有孩子   
  60.                 k = 1;  //下一个插入的应为左孩子结点   
  61.                 break;  
  62.             case ',':  
  63.                 k = 2;  //下一个插入的应为右孩子结点   
  64.                 break;  
  65.             case ')':  
  66.                 s.pop();//结点完成孩子的输入,出栈   
  67.                 break;  
  68.             default:  
  69.                 p = new BiTreeNode;  
  70.                 p->data = ch;  
  71.                 p->lchild = NULL;  
  72.                 p->rchild = NULL;  
  73.                 if(k==1)  
  74.                     s.top()->lchild = p;  
  75.                 else   
  76.                     s.top()->rchild = p;  
  77.         }         
  78.     }  
  79. }  
  80.   
  81. //以广义表的方式输出二叉树  
  82. void printBiTreeWithGenList(const BiTree&T)  
  83. {  
  84.     if(T)  
  85.     {  
  86.         cout<<T->data;  
  87.         if(T->lchild ||T->rchild)//左右子树不全空   
  88.         {  
  89.             cout<<"(";  
  90.             printBiTreeWithGenList(T->lchild);//递归输出左子树 ,可能为空   
  91.             if(T->rchild)          
  92.             {  
  93.                 cout<<",";  
  94.                 printBiTreeWithGenList(T->rchild);  
  95.             }  
  96.             cout<<")";  
  97.         }  
  98.     }  
  99. }  
  100.    
  101. //递归销毁一棵二叉树  
  102. void destroyBiTree(BiTree &T)  
  103. {  
  104.     if(T)  
  105.     {  
  106.         destroyBiTree(T->lchild);  
  107.         destroyBiTree(T->rchild);  
  108.         delete T;  
  109.         T = NULL;  
  110.     }  
  111. }   
  112.   
  113. //递归先序遍历二叉树   
  114. void preOrderTraverse(const BiTree &T)  
  115. {  
  116.     if(T)  
  117.     {  
  118.         cout<<T->data<<" ";//输出根节点值   
  119.         preOrderTraverse(T->lchild);//遍历左子树   
  120.         preOrderTraverse(T->rchild);//遍历右子树   
  121.     }  
  122. }  
  123.   
  124. //递归中序遍历二叉树  
  125. void inOrderTraverse(const BiTree &T)  
  126. {  
  127.     if(T)  
  128.     {  
  129.         inOrderTraverse(T->lchild);//遍历左子树   
  130.         cout<<T->data<<" ";//输出根节点值   
  131.         inOrderTraverse(T->rchild);//遍历右子树   
  132.     }  
  133. }  
  134.   
  135. //递归后序遍历二叉树  
  136. void postOrderTraverse(const BiTree &T)  
  137. {  
  138.     if(T)  
  139.     {  
  140.         postOrderTraverse(T->lchild);//遍历左子树   
  141.         postOrderTraverse(T->rchild);//遍历右子树   
  142.         cout<<T->data<<" ";//输出根节点值   
  143.     }   
  144. }  
  145.   
  146. //递归求树的深度   
  147. int depthOfBiTree(const BiTree &T)  
  148. {  
  149.     int ldepth;  
  150.     int rdepth;  
  151.       
  152.     if(T==NULL)//空树   
  153.         return 0;  
  154.     ldepth = depthOfBiTree(T->lchild);  
  155.     rdepth = depthOfBiTree(T->rchild);  
  156.       
  157.     return (ldepth>rdepth)?(ldepth+1):(rdepth+1);  
  158. }  
  159.   
  160. //递归求二叉树的叶子结点个数  
  161. int leafCountOfBiTree(const BiTree &T)  
  162. {     
  163.     if(T==NULL)  
  164.         return 0;  
  165.     if(T->lchild==NULL && T->rchild==NULL)  
  166.         return 1;  
  167.     return leafCountOfBiTree(T->lchild) + leafCountOfBiTree(T->rchild);  
  168. }   
  169.   
  170. //递归交换二叉树的左右子女  
  171. void exchangeChild(BiTree &T)  
  172. {  
  173.     if(T)  
  174.     {  
  175.         BiTree temp = NULL;  
  176.           
  177.         if(T->lchild ||T->rchild)  
  178.         {  
  179.             temp = T->lchild;  
  180.             T->lchild = T->rchild;  
  181.             T->rchild = temp;  
  182.             exchangeChild(T->lchild);  
  183.             exchangeChild(T->rchild);  
  184.         }  
  185.     }  
  186. }  
  187.    
  188. int main(int argc, char *argv[])  
  189. {  
  190.     BiTree T = NULL;  
  191.       
  192.     createBiTree(T);//建立二叉树 如输入AB#D##CE###   
  193. //  createBiTreeWithGenList(T);//如输入A(B(,D),C(E))#  
  194.       
  195.     cout<<"preOrder: "//先序遍历   
  196.     preOrderTraverse(T);  
  197.     cout<<endl;  
  198.       
  199.     cout<<"inOrder: ";//中序遍历   
  200.     inOrderTraverse(T);  
  201.     cout<<endl;  
  202.       
  203.     cout<<"postOrder: ";//后序遍历   
  204.     postOrderTraverse(T);  
  205.     cout<<endl;  
  206.       
  207.     cout<<"depth: "<<depthOfBiTree(T)<<endl;//树的高度   
  208.       
  209.     cout<<"the count of leaf: "<<leafCountOfBiTree(T)<<endl;//叶子结点数   
  210.       
  211.     cout<<"The tree after exchange: ";  
  212.     exchangeChild(T);  
  213.     printBiTreeWithGenList(T);  
  214.       
  215.     destroyBiTree(T);//销毁二叉树,释放空间   
  216.       
  217.     system("PAUSE");  
  218.     return EXIT_SUCCESS;  
  219. }  
注:二叉树的非递归遍历及层次遍历,请看 http://blog.csdn.net/sysu_arui/article/details/7865873

转自:http://blog.csdn.net/sysu_arui/article/details/7865876




  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值