二叉樹遍歷及C語言實現
已知中序和前序序列,或者已知中序和後序序列,都能夠構造一棵二叉樹。在本例中,本人用C語言寫程序解答了下面兩個算法題:
(1)給出一棵二叉樹的中序與後序遍歷序列,求出它的先序遍歷序列。
(2)給出一棵二叉樹的中序與先序遍歷序列,求出它的後序遍歷序列。
知識點扼要回顧:
所謂二叉樹的遍歷,是指按一定的順序對二叉樹中的每個結點均訪問一次,且僅訪問一。按照根結點訪問位置的不同,通常把二叉樹的遍歷分爲六種:
TLR(根左右), TRL(根右左), LTR(左根右)
RTL(右根左), LRT(左右根), RLT(右左根)
其中,TRL、RTL和RLT三種順序在左右子樹之間均是先右子樹後左子樹,這與人們先左後右的習慣不同,因此,往往不予採用。餘下的三種順序TLR、LTR和LRT根據根訪問的位置不同分別被稱爲前序遍歷、中序遍歷和後序遍歷。
前序遍歷的規律是:輸出根結點,輸出左子樹,輸出右子樹;
中序遍歷的規律是:輸出左子樹,輸出根結點,輸出右子樹;
後序遍歷的規律是:輸出左子樹,輸出右子樹,輸出根結點;
不多說了,看代碼吧:)
- #include <iostream>
- #include <string>
- using namespace std;
- //存儲節點數據,爲簡便起見,這裏選用字符
- typedef char DATA_TYPE;
- typedef struct tagBINARY_TREE_NODE BINARY_TREE_NODE, *LPBINARY_TREE_NODE;
- struct tagBINARY_TREE_NODE
- {
- DATA_TYPE data; //節點數據
- LPBINARY_TREE_NODE pLeftChild; //左孩子指針
- LPBINARY_TREE_NODE pRightChild; //右孩子指針
- };
- //
- //函數名稱:TreeFromMidPost
- //函數功能:給出一棵二叉樹的中序與後序序列,構造這棵二叉樹。
- //輸入參數:LPBINARY_TREE_NODE & lpNode:二叉樹的結點
- // string mid:存儲了二叉樹的中序序列的字符串
- // string post:存儲了二叉樹的後序序列的字符串
- // int lm, int rm:二叉樹的中序序列在數組mid中的左右邊界
- // int lp, int rp:二叉樹的後序序列在數組post中的左右邊界
- //
- void TreeFromMidPost(LPBINARY_TREE_NODE & lpNode, string mid, string post, int lm, int rm, int lp, int rp)
- {
- //構造二叉樹結點
- lpNode = new BINARY_TREE_NODE;
- lpNode->data = post[rp];
- lpNode->pLeftChild = NULL;
- lpNode->pRightChild = NULL;
- int pos = lm;
- while (mid[pos] != post[rp])
- {
- pos++;
- }
- int iLeftChildLen = pos - lm;
- if (pos > lm)//有左孩子,遞歸構造左子樹
- {
- TreeFromMidPost(lpNode->pLeftChild, mid, post, lm, pos - 1, lp, lp + iLeftChildLen - 1);
- }
- if (pos < rm)//有右孩子,遞歸構造右子樹
- {
- TreeFromMidPost(lpNode->pRightChild, mid, post, pos + 1, rm, lp + iLeftChildLen, rp - 1);
- }
- }
- //
- //函數名稱:TreeFromMidPre
- //函數功能:給出一棵二叉樹的先序與中序序列,構造這棵二叉樹。
- //輸入參數: BINARY_TREE_NODE & lpNode:二叉樹的結點
- // string mid:存儲了二叉樹的中序序列的字符串
- // string pre:存儲了二叉樹的先序序列的字符串
- // int lm, int rm:二叉樹的中序序列在數組mid中的左右邊界
- // int lp, int rp:二叉樹的先序序列在數組pre中的左右邊界
- //
- void TreeFromMidPre(LPBINARY_TREE_NODE & lpNode, string mid, string pre, int lm, int rm, int lp, int rp)
- {
- //構造二叉樹結點
- lpNode = new BINARY_TREE_NODE;
- lpNode->data = pre[lp];
- lpNode->pLeftChild = NULL;
- lpNode->pRightChild = NULL;
- int pos = lm;
- while (mid[pos] != pre[lp])
- {
- pos++;
- }
- int iLeftChildLen = pos - lm;
- if (pos > lm)//有左孩子,遞歸構造左子樹
- {
- TreeFromMidPre(lpNode->pLeftChild, mid, pre, lm, pos - 1, lp + 1, lp + iLeftChildLen);
- }
- if (pos < rm)//有右孩子,遞歸構造右子樹
- {
- TreeFromMidPre(lpNode->pRightChild, mid, pre, pos + 1, rm, lp + iLeftChildLen + 1, rp);
- }
- }
- //先序遍歷
- void PreOrder(LPBINARY_TREE_NODE p)
- {
- if(p != NULL)
- {
- cout << p->data; //輸出該結點
- PreOrder(p->pLeftChild); //遍歷左子樹
- PreOrder(p->pRightChild); //遍歷右子樹
- }
- }
- //中序遍歷
- void MidOrder(LPBINARY_TREE_NODE p)
- {
- if(p != NULL)
- {
- MidOrder(p->pLeftChild); //遍歷左子樹
- cout << p->data; //輸出該結點
- MidOrder(p->pRightChild); //遍歷右子樹
- }
- }
- //後序遍歷
- void PostOrder(LPBINARY_TREE_NODE p)
- {
- if(p != NULL)
- {
- PostOrder(p->pLeftChild); //遍歷左子樹
- PostOrder(p->pRightChild); //遍歷右子樹
- cout << p->data; //輸出該結點
- }
- }
- //釋放二叉樹
- void Release(LPBINARY_TREE_NODE lpNode)
- {
- if(lpNode != NULL)
- {
- Release(lpNode->pLeftChild);
- Release(lpNode->pRightChild);
- delete lpNode;
- lpNode = NULL;
- }
- }
- int main(int argc, char* argv[])
- {
- string pre; //存儲先序序列
- string mid; //存儲中序序列
- string post; //存儲後序序列
- LPBINARY_TREE_NODE lpRoot; //二叉樹根節點指針
- cout<<"程序1已知二叉樹的中序與後序序列,求先序序列"<<endl;
- cout<<"請先輸入中序序列,回車後輸入後序序列:"<<endl;
- cin >> mid;
- cin >> post;
- TreeFromMidPost(lpRoot, mid, post, 0, mid.size()-1, 0, post.size()-1);
- cout<<"先序遍歷結果:";
- PreOrder(lpRoot);
- cout<<endl;
- cout<<"中序遍歷結果:";
- MidOrder(lpRoot);
- cout<<endl;
- cout<<"後序遍歷結果:";
- PostOrder(lpRoot);
- cout<<endl;
- Release(lpRoot);
- cout<<endl;
- cout<<"程序2已知二叉樹的中序與先序序列,求後序序列"<<endl;
- cout<<"請先輸入先序序列,回車後輸入中序序列:"<<endl;
- cin >> pre;
- cin >> mid;
- TreeFromMidPre(lpRoot, mid, pre, 0, mid.size()-1, 0, pre.size()-1);
- cout<<"先序遍歷結果:";
- PreOrder(lpRoot);
- cout<<endl;
- cout<<"中序遍歷結果:";
- MidOrder(lpRoot);
- cout<<endl;
- cout<<"後序遍歷結果:";
- PostOrder(lpRoot);
- cout<<endl;
- Release(lpRoot);
- cout<<endl;
- system("pause");
- return 0;
- }
(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 ☆程序天堂☆ 請尊重作者原創,轉載註明來自裂帛一劍博客,謝謝合作。