7665 views
# Binary Tree 二元樹 ## 定義 二元樹是一種特殊的樹。在二元樹中,每個內部節點的最多只有兩個child,分別是左子樹和右子樹,而左子樹和右子樹也都是二元樹。此外,二元樹可以為空。 * 樹 (tree) 與二元樹 (binary tree) 的比較 |樹 tree|二元樹 binary tree| |:----:|:----:| |不可以為空|可以為空(空集合)| |Node's degree $\geq$ 0即可|0 $\leq$ Node's degree $\leq$ 2| |子樹之間無次序/方向之分|子樹有左右之分| ## 基本定理 **定理一 :** 令root level=1。二元樹中第 $i$ level 之最多node數 = ==$2^{i-1}$個==。($i\geq1$) :::info **<pf>**(數學歸納法) 1.當level=$1$時,最多只有root一個點,符合$2^{1-1}=2^0=1$,初值成立。 2.令level=$i-1$時,此定理成立。 3.當level=$i$時,其最多Node數必定是 =$(第i-1個$level$之最多$Node$數)×2=2^{(i-1)-1}×2=2^{i-1}$。 因此,由數學歸納法得證。 ::: **定理二 :** 令root level=1。高度為$K$之Binary Tree,其最多的Node數= ==$2^K-1$==。 :::info **<pf>** $\sum^k_{i=1}$(level $i$ 之Node數) =2^0^+2^1^+2^2^+...+2^K-1^=(2^(K-1)+1^-2^0^)/(2-1)=2^K^-1 ::: **定理二(反向) :** 令root level=1。若Binary Tree 有$n$個node,則最小高度 = ==$\lceil\log_2(n+1)\rceil$== ,最大高度 = ==$n$==。 :::info **<pf>** $2^K-1=n\rightarrow2^K=n+1\rightarrow K=\log_2(n+1)$ ::: **定理三 :** 令root level=1。給定一個非空的Binary Tree,若Leaf的個數有$n_0$個,Degree=$2$的node個數有$n_2$個,則 ==$n_0=n_2+1$==。 :::info **<pf>** 假設N代表Node總數,N~i~代表degree=i之Node數,B代表分支(Branch)總數。 $\rightarrow N=N_0+N_1+N_2=B+1=[N_1+2×N_2]+1$ $\rightarrow N_0+N_1+N_2=[N_1+2×N_2]+1$ $\rightarrow N_0=N_2+1$ ::: ## 種類 ### Skewed B.T. 歪斜樹 可分為兩種: * **left-skewed B.T.** 每個non-leaf皆只有左子點,沒有右子點。 ```graphviz digraph skewed{ b1[label="A"] b2[label="B"] b3[label="NULL";color=none] b4[label="C"] b5[label="NULL";color=none] b1->b2; b1->b3[style=dashed]; b2->b4; b2->b5[style=dashed]; } ``` * **right-skewed B.T.** 每個non-leaf皆只有左子點,沒有右子點。 ```graphviz digraph skewed{ b1[label="A"] b2[label="NULL";color=none] b3[label="B"] b4[label="NULL";color=none] b5[label="C"] b1->b2[style=dashed]; b1->b3; b3->b4[style=dashed]; b3->b5; } ``` ### Full B.T. 高度為K,具有最多Node數者(2^K^-1),稱之。 ```graphviz digraph{ a->b[weight=1] a->c[weight=1] b->d[weight=2] b->e[weight=1] c->f[weight=1] c->g[weight=2] } ``` ### Complete B.T. 高度為K,Node數為N的二元樹,滿足 (1) 2^k-1^-1 < N < 2^K^-1 (2) Node的編號順序與==同高度的 Full B.T.== 的前N個Node編號一一對應。(即Node的增長順是由上至下,由左而右依序增長) ```graphviz digraph{ a b c d e f[style=dashed] g[style=dashed] a->b[weight=1] a->c[weight=1] b->d[weight=2] b->e[weight=1] c->f[weight=1;style=dashed] c->g[weight=2;style=dashed] } ``` :::info * Complete B.T. 之定理: 一個Complete B.T.有N個Node編號:1~n,若某Node編號為 $i$,則 (1) 其左子點編號:$2i$ (若$2i>n$,則無左子點) (2) 其右子點編號:$2i+1$ (若$2i+1>n$,則無右子點) (3) 其父點編號:$[\frac{i}{2}]$ (取整數) (若$[\frac{i}{2}]<1$,則無父點) <pf>(數學歸納法,只要證(1),(2)自然得證,再由(1)(2),(3)自然得證) (1)當$i=1$時,此點必為root,而root若有左子點,必為root的下一個Node,因此編號為 $2$,滿足$2×i=2×1=2$,初值成立。 (2)令編號$\geq i-1$時,此定理成立。 (3)當編號$=i$時,其左子點的編號必為編號$i-1$的Node的左子點編號$+2$,得到$2(i-1)+2=2$。 因此,由數學歸納法得證。 ::: ## strict B.T. (嚴格的) 在B.T.中,任何的non-leaf必有兩個子點。 ## Binary Tree Traversal (尋訪) Binary Tree 的 Node具有指向兩個 child 的 pointer , traversal 以當前所在的 Node 為基準,所能做的事情有三種: * V : Visiting,在當前所在的Node進行print out(顯示資料)、assign(賦值)、刪除資料等等。 * L : 移動到 left child。 * R : 移動到 right child。 ```graphviz digraph graphname{ subgraph cluster_visit{ label="V"; fontcolor=red; color=none; A[label="A"; color=red;]; } subgraph{ B[label="B"]; C[label="C"]; } A->B[label="L"; color=blue; fontcolor=blue] A->C[label="R"; color=green; fontcolor=green] } ``` 以上面的圖為例,假設CurrentNode在A,leftchild和rightchild分別是B和C,加上一項限制:「L一定要在R之前」,便能產生三種尋訪的方式 : * **前序走訪 pre-order(VLR)** 先對**A**進行Visiting,接著前往left child(**B**)進行Visiting,再前往right child (**C**)進行Visiting。 (若child指向NULL則忽略。) * **中序走訪 in-order(LVR)** 先對A的left child(**B**)進行 Visiting,接著回到**A**進行Visiting,在前往right child(**C**)進行Visiting。 (若child指向NULL則忽略。) * **後序走訪 post-order(LRV)** 先對A的left child(**B**)進行 Visiting,接著到A的right child(**C**)進行Visiting,再回到**A**進行Visiting。 (若child指向NULL則忽略。) 此外,還有一種尋訪的方式,照著「level由小到大」的順序,由上而下,並在同一個level「由左至右」依序Visiting每個node。我們稱為 **「Level-Order Traversal」**。 ### 範例 ```graphviz digraph{ subgraph cluster{ A B C } D E A->B; A->C; B->D; B->E; } ``` ```graphviz digraph{ A subgraph cluster{ label=V B D E } C A->B; A->C; B->D[weight=2]; B->E[weight=1]; } ``` ```graphviz digraph{ subgraph cluster{ label=V fontcolor=red D[color=red] F[label=NULL;style=dashed] G[label=NULL;style=dashed] } A->B; A->C; B->D[weight=2]; B->E[weight=2]; D->F[weight=3;label=L;color=green;fontcolor=green]; D->G[weight=1;label=R;color=green;fontcolor=green]; } ``` pre-order : A->B->D->E->C in-order : D->B->E->A->C post-order : D->E->B->C->A level-order : A->B->C->D->E ### 程式碼 ```C= #include<stdio.h> #include<stdlib.h> typedef struct node { int data; struct node *left; struct node *right; } node; typedef struct QueueNode{ node *Q; struct QueueNode *next; } Queue; Queue *front, *rear; front = rear = NULL; node *create() { node *p; int x; printf("Enter data(-1 for no node):"); scanf("%d",&x); if(x==-1) return NULL; p=(node*)malloc(sizeof(node)); p->data=x; printf("Enter left child of %d:\n",x); p->left=create(); printf("Enter right child of %d:\n",x); p->right=create(); return p; } int isEmpty(){ if (front == NULL){ return 1; } else{ return 0; } } void enqueue(node *a){ Queue *newnode = (Queue*)malloc(sizeof(Queue)); newnode->Q = a; newnode->next = NULL; if (front==NULL){ front = newnode; rear = newnode; return; } rear->next = newnode; rear = newnode; } node* dequeue(){ Queue *tmp; node *address; int value; if (front == NULL){ printf("Queue error!"); return NULL; } else{ tmp = front; address = front->Q; front = front->next; free(tmp); return address; } } void levelorder(node *t){ if (t == NULL){ return; } enqueue(t); while (!isEmpty()){ node *current = front->Q; printf(" %d",current->data); if (current->left!=NULL){ enqueue(current->left); } if (current->right!=NULL){ enqueue(current->right); } dequeue(); } } void preorder(node *t) { if(t!=NULL) { printf(" %d",t->data); preorder(t->left); preorder(t->right); } } void inorder(node *t) { if(t!=NULL) { inorder(t->left); printf(" %d",t->data); inorder(t->right); } } void postorder(node *t) { if(t!=NULL) { postorder(t->left); postorder(t->right); printf(" %d",t->data); } } int main() { node *root; root=create(); printf("\nThe preorder traversal of tree is: "); preorder(root); printf("\nThe inorder traversal of tree is: "); inorder(root); printf("\nThe postorder traversal of tree is: "); postorder(root); printf("\nThe levelorder traversal of tree is: "); levelorder(root); return 0; } ``` 結果 :::success Enter data(-1 for no node):1 Enter left child of 1: Enter data(-1 for no node):2 Enter left child of 2: Enter data(-1 for no node):-1 Enter right child of 2: Enter data(-1 for no node):-1 Enter right child of 1: Enter data(-1 for no node):3 Enter left child of 3: Enter data(-1 for no node):-1 Enter right child of 3: Enter data(-1 for no node):-1 The preorder traversal of tree is: 1 2 3 The inorder traversal of tree is: 2 1 3 The postorder traversal of tree is: 2 3 1 The levelorder traversal of tree is: 1 2 3 :::