最近學習樹的概念,有關二叉樹的實現算法記錄下來。。。html
不過學習以前要了解的預備知識:樹的概念;二叉樹的存儲結構;二叉樹的遍歷方法。。ios
二叉樹的存儲結構主要了解二叉鏈表結構,也就是一個數據域,兩個指針域,(分別爲指向左右孩子的指針),從下面程序1,二叉樹的存儲結構能夠看出。c++
二叉樹的遍歷方法:主要有前序遍歷,中序遍歷,後序遍歷,層序遍歷。(層序遍歷下一篇再講,本篇主要講的遞歸法)算法
下篇主要是非遞歸遍歷,以後會有c++模板實現 二叉樹 和 二叉搜索樹(用於動態查找)。數據結構
如這樣一個二叉樹:
函數
它的前序遍歷順序爲:ABDGHCEIF(規則是先是根結點,再前序遍歷左子樹,再前序遍歷右子樹)學習
它的中序遍歷順序爲:GDHBAEICF(規則是先中序遍歷左子樹,再是根結點,再是中序遍歷右子樹)spa
它的後序遍歷順序爲:GHDBIEFCA(規則是前後序遍歷左子樹,再是後序遍歷右子樹,再是根結點)指針
若是不懂的話,能夠參看有關數據結構的書籍。。調試
1,二叉樹的存儲結構(二叉鏈表)
//二叉樹的二叉鏈表結構,也就是二叉樹的存儲結構,1個數據域,2個指針域(分別指向左右孩子) typedef struct BiTNode { ElemType data; struct BiTNode *lchild, *rchild; }BiTNode, *BiTree;
2,首先要創建一個二叉樹,創建二叉樹必需要了解二叉樹的遍歷方法。
//二叉樹的創建,按前序遍歷的方式創建二叉樹,固然也能夠以中序或後序的方式創建二叉樹 void CreateBiTree(BiTree *T) { ElemType ch; cin >> ch; if (ch == '#') *T = NULL; //保證是葉結點 else { *T = (BiTree)malloc(sizeof(BiTNode)); //if (!*T) //exit(OVERFLOW); //內存分配失敗則退出。 (*T)->data = ch;//生成結點 CreateBiTree(&(*T)->lchild);//構造左子樹 CreateBiTree(&(*T)->rchild);//構造右子樹 } }
3.二叉樹的遍歷(遞歸方式,非遞歸方式見下篇:樹(二叉樹)的創建和遍歷算法(二)):
主要有三種方法:
/遞歸方式前序遍歷二叉樹 void PreOrderTraverse(BiTree T, int level) { if (T == NULL) return;
/*此處表示對遍歷的樹結點進行的操做,根據你本身的要求進行操做,這裏只是輸出告終點的數據*/ //operation1(T->data); operation2(T->data, level); //輸出了層數 PreOrderTraverse(T->lchild, level + 1); PreOrderTraverse(T->rchild, level + 1); } //遞歸方式中序遍歷二叉樹 void InOrderTraverse(BiTree T,int level) { if(T==NULL) return; InOrderTraverse(T->lchild,level+1); //operation1(T->data); operation2(T->data, level); //輸出了層數 InOrderTraverse(T->rchild,level+1); } //遞歸方式後序遍歷二叉樹 void PostOrderTraverse(BiTree T,int level) { if(T==NULL) return; PostOrderTraverse(T->lchild,level+1); PostOrderTraverse(T->rchild,level+1); //operation1(T->data); operation2(T->data, level); //輸出了層數 }
4.完整代碼:
#include<iostream> #include<stdlib.h> using namespace std; typedef char ElemType; //二叉樹的二叉鏈表結構,也就是二叉樹的存儲結構,1個數據域,2個指針域(分別指向左右孩子) typedef struct BiTNode { ElemType data; struct BiTNode *lchild, *rchild; }BiTNode, *BiTree; //二叉樹的創建,按前序遍歷的方式創建二叉樹,固然也能夠以中序或後序的方式創建二叉樹 void CreateBiTree(BiTree *T) { ElemType ch; cin >> ch; if (ch == '#') *T = NULL; //保證是葉結點 else { *T = (BiTree)malloc(sizeof(BiTNode)); //if (!*T) //exit(OVERFLOW); //內存分配失敗則退出。 (*T)->data = ch;//生成結點 CreateBiTree(&(*T)->lchild);//構造左子樹 CreateBiTree(&(*T)->rchild);//構造右子樹 } } //表示對遍歷到的結點數據進行的處理操做,此處操做是將樹結點前序遍歷輸出 void operation1(ElemType ch) { cout << ch << " "; } //此處在輸出的基礎上,並輸出層數 void operation2(ElemType ch, int level) { cout << ch << "在第" << level << "層" << endl; } //遞歸方式前序遍歷二叉樹 void PreOrderTraverse(BiTree T, int level) { if (T == NULL) return; /*此處表示對遍歷的樹結點進行的操做,根據你本身的要求進行操做,這裏只是輸出告終點的數據*/ //operation1(T->data); operation2(T->data, level); //輸出了層數 PreOrderTraverse(T->lchild, level + 1); PreOrderTraverse(T->rchild, level + 1); } //遞歸方式中序遍歷二叉樹 void InOrderTraverse(BiTree T,int level) { if(T==NULL) return; InOrderTraverse(T->lchild,level+1); //operation1(T->data); operation2(T->data, level); //輸出了層數 InOrderTraverse(T->rchild,level+1); } //遞歸方式後序遍歷二叉樹 void PostOrderTraverse(BiTree T,int level) { if(T==NULL) return; PostOrderTraverse(T->lchild,level+1); PostOrderTraverse(T->rchild,level+1); //operation1(T->data); operation2(T->data, level); //輸出了層數 } int main() { int level = 1; //表示層數 BiTree T = NULL; cout << "請之前序遍歷的方式輸入擴展二叉樹:"; //相似輸入AB#D##C## CreateBiTree(&T);// 創建二叉樹,沒有樹,怎麼遍歷 cout << "遞歸前序遍歷輸出爲:" << endl; PreOrderTraverse(T, level);//進行前序遍歷,其中operation1()和operation2()函數表示對遍歷的結點數據進行的處理操做 cout << endl; cout << "遞歸中序遍歷輸出爲:" << endl; InOrderTraverse(T, level); cout << endl; cout << "遞歸後序遍歷輸出爲:" << endl; PostOrderTraverse(T, level); cout << endl; return 0; }
注意:這裏有幾個知識點補充下:
(1)創建二叉樹時,這裏是之前序遍歷的方式,輸入的是擴展二叉樹,也就是要告訴計算機什麼是葉結點,不然將一直遞歸,當輸入「#」時,指針指向NULL,說明是葉結點。
如圖爲擴展二叉樹:(前序遍歷爲:ABDG##H###CE#I##F##)
(2)operation1( )函數只是對各個結點的輸出;
operation2( )函數不只輸出了各個結點,同時輸出告終點所在的層數。(調試時能夠只先運行一個)
5.運行結果
只是運行了operation2( )函數,有層數輸出:
或者運行只運行operation1( )函數