二叉樹的基本操作


二叉樹作爲一種非常重要的數據結構,今天對其做簡單的回顧
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




發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章