【zz】二叉樹遍歷及C語言實現

二叉樹遍歷及C語言實現

已知中序和前序序列,或者已知中序和後序序列,都能夠構造一棵二叉樹。在本例中,本人用C語言寫程序解答了下面兩個算法題:

(1)給出一棵二叉樹的中序與後序遍歷序列,求出它的先序遍歷序列。

(2)給出一棵二叉樹的中序與先序遍歷序列,求出它的後序遍歷序列。

知識點扼要回顧:
所謂二叉樹的遍歷,是指按一定的順序對二叉樹中的每個結點均訪問一次,且僅訪問一。按照根結點訪問位置的不同,通常把二叉樹的遍歷分爲六種:
TLR(根左右), TRL(根右左), LTR(左根右)
RTL(右根左), LRT(左右根), RLT(右左根)

其中,TRL、RTL和RLT三種順序在左右子樹之間均是先右子樹後左子樹,這與人們先左後右的習慣不同,因此,往往不予採用。餘下的三種順序TLR、LTR和LRT根據根訪問的位置不同分別被稱爲前序遍歷、中序遍歷和後序遍歷。

前序遍歷的規律是:輸出根結點,輸出左子樹,輸出右子樹;  
中序遍歷的規律是:輸出左子樹,輸出根結點,輸出右子樹; 
後序遍歷的規律是:輸出左子樹,輸出右子樹,輸出根結點;

不多說了,看代碼吧:)

 

  1. #include <iostream>  
  2. #include <string>  
  3.   
  4. using namespace std;  
  5.   
  6. //存儲節點數據,爲簡便起見,這裏選用字符  
  7. typedef char   DATA_TYPE;  
  8.   
  9. typedef struct tagBINARY_TREE_NODE  BINARY_TREE_NODE, *LPBINARY_TREE_NODE;  
  10.   
  11. struct tagBINARY_TREE_NODE  
  12. {  
  13.       DATA_TYPE             data;           //節點數據  
  14.       LPBINARY_TREE_NODE    pLeftChild;     //左孩子指針  
  15.       LPBINARY_TREE_NODE    pRightChild;    //右孩子指針  
  16. };  
  17.   
  18. //  
  19. //函數名稱:TreeFromMidPost  
  20. //函數功能:給出一棵二叉樹的中序與後序序列,構造這棵二叉樹。   
  21. //輸入參數:LPBINARY_TREE_NODE & lpNode:二叉樹的結點   
  22. //          string mid:存儲了二叉樹的中序序列的字符串   
  23. //          string post:存儲了二叉樹的後序序列的字符串   
  24. //          int lm, int rm:二叉樹的中序序列在數組mid中的左右邊界   
  25. //          int lp, int rp:二叉樹的後序序列在數組post中的左右邊界  
  26. //  
  27. void TreeFromMidPost(LPBINARY_TREE_NODE & lpNode, string mid, string post, int lm, int rm, int lp, int rp)  
  28. {  
  29.     //構造二叉樹結點  
  30.     lpNode = new BINARY_TREE_NODE;  
  31.     lpNode->data = post[rp];  
  32.     lpNode->pLeftChild = NULL;  
  33.     lpNode->pRightChild = NULL;  
  34.   
  35.     int pos = lm;  
  36.   
  37.     while (mid[pos] != post[rp])  
  38.     {  
  39.         pos++;  
  40.     }  
  41.     int iLeftChildLen = pos - lm;  
  42.   
  43.     if (pos > lm)//有左孩子,遞歸構造左子樹  
  44.     {  
  45.         TreeFromMidPost(lpNode->pLeftChild, mid, post, lm, pos - 1, lp, lp + iLeftChildLen - 1);  
  46.     }  
  47.   
  48.     if (pos < rm)//有右孩子,遞歸構造右子樹  
  49.     {  
  50.         TreeFromMidPost(lpNode->pRightChild, mid, post, pos + 1, rm, lp + iLeftChildLen, rp - 1);  
  51.     }  
  52. }  
  53.   
  54. //  
  55. //函數名稱:TreeFromMidPre  
  56. //函數功能:給出一棵二叉樹的先序與中序序列,構造這棵二叉樹。   
  57. //輸入參數: BINARY_TREE_NODE & lpNode:二叉樹的結點  
  58. //          string mid:存儲了二叉樹的中序序列的字符串   
  59. //          string pre:存儲了二叉樹的先序序列的字符串   
  60. //          int lm, int rm:二叉樹的中序序列在數組mid中的左右邊界   
  61. //          int lp, int rp:二叉樹的先序序列在數組pre中的左右邊界  
  62. //  
  63. void TreeFromMidPre(LPBINARY_TREE_NODE & lpNode, string mid, string pre, int lm, int rm, int lp, int rp)  
  64. {  
  65.     //構造二叉樹結點  
  66.     lpNode = new BINARY_TREE_NODE;  
  67.     lpNode->data = pre[lp];  
  68.     lpNode->pLeftChild = NULL;  
  69.     lpNode->pRightChild = NULL;  
  70.   
  71.     int pos = lm;  
  72.   
  73.     while (mid[pos] != pre[lp])  
  74.     {  
  75.         pos++;  
  76.     }  
  77.     int iLeftChildLen = pos - lm;  
  78.   
  79.     if (pos > lm)//有左孩子,遞歸構造左子樹  
  80.     {  
  81.         TreeFromMidPre(lpNode->pLeftChild, mid, pre, lm, pos - 1, lp + 1, lp + iLeftChildLen);  
  82.     }  
  83.   
  84.     if (pos < rm)//有右孩子,遞歸構造右子樹  
  85.     {  
  86.         TreeFromMidPre(lpNode->pRightChild, mid, pre, pos + 1, rm, lp + iLeftChildLen + 1, rp);  
  87.     }  
  88. }  
  89.   
  90. //先序遍歷  
  91. void PreOrder(LPBINARY_TREE_NODE p)  
  92. {  
  93.        if(p != NULL)  
  94.        {  
  95.               cout << p->data;          //輸出該結點  
  96.               PreOrder(p->pLeftChild);  //遍歷左子樹   
  97.               PreOrder(p->pRightChild); //遍歷右子樹  
  98.        }  
  99. }  
  100.   
  101. //中序遍歷  
  102. void MidOrder(LPBINARY_TREE_NODE p)  
  103. {  
  104.        if(p != NULL)  
  105.        {  
  106.               MidOrder(p->pLeftChild);   //遍歷左子樹   
  107.               cout << p->data;           //輸出該結點  
  108.               MidOrder(p->pRightChild);  //遍歷右子樹  
  109.        }  
  110. }  
  111.   
  112. //後序遍歷  
  113. void PostOrder(LPBINARY_TREE_NODE p)  
  114. {  
  115.        if(p != NULL)  
  116.        {  
  117.               PostOrder(p->pLeftChild);  //遍歷左子樹   
  118.               PostOrder(p->pRightChild); //遍歷右子樹  
  119.               cout << p->data;           //輸出該結點  
  120.        }  
  121. }  
  122.   
  123. //釋放二叉樹  
  124. void Release(LPBINARY_TREE_NODE lpNode)  
  125. {  
  126.     if(lpNode != NULL)  
  127.     {  
  128.         Release(lpNode->pLeftChild);  
  129.         Release(lpNode->pRightChild);  
  130.         delete lpNode;  
  131.         lpNode = NULL;  
  132.     }  
  133. }  
  134.   
  135.   
  136. int main(int argc, char* argv[])  
  137. {  
  138.     string              pre;            //存儲先序序列  
  139.     string              mid;            //存儲中序序列  
  140.     string              post;           //存儲後序序列  
  141.   
  142.     LPBINARY_TREE_NODE  lpRoot;         //二叉樹根節點指針  
  143.   
  144.   
  145.     cout<<"程序1已知二叉樹的中序與後序序列,求先序序列"<<endl;  
  146.     cout<<"請先輸入中序序列,回車後輸入後序序列:"<<endl;  
  147.   
  148.     cin >> mid;  
  149.     cin >> post;  
  150.   
  151.     TreeFromMidPost(lpRoot, mid, post, 0, mid.size()-1, 0, post.size()-1);  
  152.     cout<<"先序遍歷結果:";  
  153.     PreOrder(lpRoot);  
  154.     cout<<endl;  
  155.   
  156.     cout<<"中序遍歷結果:";  
  157.     MidOrder(lpRoot);  
  158.     cout<<endl;  
  159.   
  160.     cout<<"後序遍歷結果:";  
  161.     PostOrder(lpRoot);  
  162.     cout<<endl;  
  163.     Release(lpRoot);  
  164.     cout<<endl;  
  165.   
  166.     cout<<"程序2已知二叉樹的中序與先序序列,求後序序列"<<endl;  
  167.     cout<<"請先輸入先序序列,回車後輸入中序序列:"<<endl;  
  168.     cin >> pre;  
  169.     cin >> mid;  
  170.   
  171.     TreeFromMidPre(lpRoot, mid, pre, 0, mid.size()-1, 0, pre.size()-1);  
  172.     cout<<"先序遍歷結果:";  
  173.     PreOrder(lpRoot);  
  174.     cout<<endl;  
  175.   
  176.     cout<<"中序遍歷結果:";  
  177.     MidOrder(lpRoot);  
  178.     cout<<endl;  
  179.   
  180.     cout<<"後序遍歷結果:";  
  181.     PostOrder(lpRoot);  
  182.     cout<<endl;  
  183.     Release(lpRoot);  
  184.     cout<<endl;  
  185.   
  186.   
  187.     system("pause");  
  188.     return 0;  
  189. }  

 

(1)程序1的輸入方式:
已知二叉樹的中序與後序序列,求先序序列,請先輸入中序序列,回車後輸入後序序列:
例如輸入:
DGBAECHF
GDBEHFCA
輸出:
先序遍歷結果:ABDGCEFH
中序遍歷結果:DGBAECHF
後序遍歷結果:GDBEHFCA

(2)程序2的輸入方式:
已知二叉樹的先序與中序序列,求後序序列,請先輸入先序序列,回車後輸入中序序列:
例如輸入:
abdefgc
debgfac
輸出:
先序遍歷結果:abdefgc
中序遍歷結果:debgfac
後序遍歷結果:edgfbca

最後請看該程序運行效果圖:

這是程序1所確定的二叉樹圖:

這是程序2所確定的二叉樹圖:

by Loomman, QQ:28077188, MSN: [email protected] QQ裙:30515563 ☆程序天堂☆ 請尊重作者原創,轉載註明來自裂帛一劍博客,謝謝合作。

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