PS:樹型結構是一種重要的非線性數據結構,教科書上通常都是樹與二叉樹,因而可知,樹和二叉樹是有區別和聯繫的,網上有人說二叉樹是樹的一種特殊形式,但通過查資料,樹和二叉樹沒有一個確定的說法,但惟一能夠確定都是樹型結構。可是按照定義來看二叉樹並非樹的一種特殊形式(下面解釋)。樹型數據結構的做用能夠表示數據元素之間一對多的關係,一個公司裏的各個部門均可以用樹形來表示。算法
(1)徹底二叉樹 ——若設二叉樹的高度爲h,除第 h 層外,其它各層 (1~h-1) 的結點數都達到最大個數,第h層有葉子結點,而且葉子結點都是從左到右依次排布,這就是徹底二叉樹。數據結構
(2)滿二叉樹 ——除了葉結點外每個結點都有左右子葉且葉子結點都處在最底層的二叉樹。函數
(3)平衡二叉樹——平衡二叉樹又被稱爲AVL樹(區別於AVL算法),它是一棵二叉排序樹,且具備如下性質:它是一棵空樹或它的左右兩個子樹的高度差的絕對值不超過1,而且左右兩個子樹都是一棵平衡二叉樹。測試
/*
劉志通
**/
typedef struct twoCha { char data; struct twoCha *Lchild, *Rchild;//左右孩子結點 } twoCha, *twoChaL;
當咱們在鍵盤上敲了一行的char類型數據,能夠按照必定的結構儲存在計算機上,就要寫一個算法,二叉樹分左右孩子,因此,若是沒有左(右)孩子就輸入一個空格或者#,表明空。若是有左(右)孩子就新建一個結點,來存放該結點的數據data。ui
int createTwo(twoChaL &tL) { char ch; scanf("%c",&ch); if (ch == '#') { tL = NULL; return 0; } else { tL= (twoChaL)malloc(sizeof(twoCha)); if (tL == NULL) { printf("錯誤tl=NULL\n"); return 0; } else { tL->data = ch; createTwo(tL->Lchild); createTwo(tL->Rchild); } } return 0; }
畫的很差,湊活着看吧。spa
咱們以這個二叉樹爲例子,來分析他的遍歷形式,遍歷分爲三種code
void diGuiBianLi(twoChaL &tL,int xl) { if (tL == NULL) { return; } else { if(xl == 1){ //先序遍歷 printf("%c ",tL->data); diGuiBianLi(tL->Lchild,xl); diGuiBianLi(tL->Rchild,xl); }else if(xl == 2){ //中序遍歷 diGuiBianLi(tL->Lchild,xl); printf("%c ",tL->data); diGuiBianLi(tL->Rchild,xl); } else if(xl == 3){ //後序遍歷 diGuiBianLi(tL->Lchild,xl); diGuiBianLi(tL->Rchild,xl); printf("%c ",tL->data); } } }
遞歸的代碼很是少,可是一開始接觸 理解起來仍是比較難的,固然,你一旦理解後,那就很是簡單了。遞歸的思想就是把一個大問題分紅多個相似的小問題解決。blog
方法:查找一個結點沒有左右孩子,就是葉子結點。能夠定義一個static int count變量,若是該結點沒有左右結點那麼就讓count++;排序
int leafCount(twoChaL &tL) { static int count; if (tL != NULL) { if (tL->Lchild == NULL && tL->Rchild == NULL) { count++; } leafCount(tL->Lchild); leafCount(tL->Rchild); } return count; }
方法:看結點的左孩子和右孩子哪個更長,當深刻到最低結點時,左右孩子比較,誰大誰加一(相等左孩子加一)。遞歸
int treeDeep(twoChaL &tL) { int deep = 0; if (tL != NULL) { int leftdeep = treeDeep(tL->Lchild); int rightdeep = treeDeep(tL->Rchild); deep = leftdeep >= rightdeep?leftdeep+1:rightdeep+1; } return deep; }
這裏以中序爲例,利用棧的知識點(順序棧),首先把根節點進棧,而後依次左孩子進棧,直到左孩子爲NULL時結束,可是NULL也是入棧的,而後再把NULL出棧,下一步就是把棧頂元素取出並打印,再把該棧頂元素的右孩子進棧,無論右孩子是否是NULL都要入棧,入棧以前把棧頂元素彈棧。
定義棧的data域,要用結點的結構體
int top = -1; //棧 void push(twoChaL *a,twoChaL elem){ a[++top]=elem; } //彈棧函數 void pop(){ if (top==-1) { return ; } top--; } //拿到棧頂元素 twoChaL getTop(twoChaL *a){ return a[top]; } void zhongXu2(twoChaL Tree){ //順序棧 twoChaL a[100]; twoChaL p; push(a, Tree);//根結點進棧 while (top!=-1) {//top!=-1說明棧內不爲空 while ((p=getTop(a)) &&p){//取棧頂元素,且不能爲NULL push(a, p->Lchild);//將該結點的左孩子進棧,若是沒有左孩子,NULL進棧 } pop();//跳出循環,棧頂元素確定爲NULL,將NULL彈棧 /* //測試數據,主要觀察棧中NULL出棧後,還有什麼在棧中(棧頂), if(a[top]){ printf(" 跳出循環 %c\n",a[top]->data); }*/ if (top!=-1) { p=getTop(a);//取棧頂元素 pop();//棧頂元素彈棧 printf("%c ",p->data); push(a, p->Rchild);//將p指向的結點的右孩子進棧 } } }
討論羣