樹的基本概念與二叉樹相關
阿新 • • 發佈:2021-11-03
基本概念:(雙親,兄弟,堂兄弟等不在這裡贅述)
結點(node):包含一個數據元素及若干指向其子樹的分支
結點的度(degree):結點擁有子樹的個數
樹的度:樹中所有結點的度的最大值
葉子結點(leaf):度為0的結點
二叉樹的性質:
1.在二叉樹的第i層至多有2^(i-1)個結點
example
1
2 3
4 5 6 7
** 第2層有2^1
** 第3層有2^4
2.深度為k的二叉樹至多有2^k-1個結點
example:
如上二叉樹:深度為3 總共2^3-1=7個node
3.對於任意一個二叉樹T,若終端結點為n0,度為2的結點數為n2,n0=n2+1;
example:
如上二叉樹:終端結點4,度數為2的結點n2=3
**完全二叉樹: 1.所有葉子結點只能出現在層號最大的兩層上; 2.對任意節點,若其右子樹的層高為k,左子樹必為k或k+1;
4.具有n個結點的完全二叉樹的深度為[log2(n)]+1
5.對於具有n個結點的完全二叉樹,如果按照對滿二叉樹的方式進行順序編號,對於任意序號為i的結點有: 1)i=1; 結點i為root,無parent;i>1則parent=i/2 2) 2i<=n; 結點i的左孩子結點序號為2i否則無左孩子 3)2i+1<=n;結點i的右孩子結點序號為2i+1否則無右孩子
二叉樹的儲存: 1.對於滿二叉樹以及完全二叉樹的適合儲存(順序儲存結構) 由性質5我們可以將標號為i的左孩子下標為2i,右孩子下標為2i+1,雙親的結點下標為[i/2]; 二叉樹的儲存結構定義:
二叉樹的遍歷: 1.遞迴實現: A、先序遍歷:root->left->right B、中序遍歷:left->root->right C、後序遍歷:right->left->root
2.非遞迴實現 先序遍歷的實現: 1)訪問root,root入棧並進入其左子樹,進而訪問左子樹的root併入棧,在進入下一層左子樹,...直到為空 2)棧非空則從棧頂退出上一層的結點,並進入該節點的右子樹
後序遍歷: 1.當前結點進棧,並進入其左子樹,重複至當前結點為空; 2.若棧非空,判斷棧頂結點P的右子樹是否為空,右子樹是否訪問過,是則退棧
**完全二叉樹: 1.所有葉子結點只能出現在層號最大的兩層上; 2.對任意節點,若其右子樹的層高為k,左子樹必為k或k+1;
4.具有n個結點的完全二叉樹的深度為[log2(n)]+1
5.對於具有n個結點的完全二叉樹,如果按照對滿二叉樹的方式進行順序編號,對於任意序號為i的結點有: 1)i=1; 結點i為root,無parent;i>1則parent=i/2 2) 2i<=n; 結點i的左孩子結點序號為2i否則無左孩子 3)2i+1<=n;結點i的右孩子結點序號為2i+1否則無右孩子
二叉樹的儲存: 1.對於滿二叉樹以及完全二叉樹的適合儲存(順序儲存結構) 由性質5我們可以將標號為i的左孩子下標為2i,右孩子下標為2i+1,雙親的結點下標為[i/2]; 二叉樹的儲存結構定義:
1 #define MAX 100 2 typedef struct{ 3 int Sqsitree[MAX+1]; //0號單元不用 4 int nodemax; //陣列中最後一個節點的下標 5 }Bitree;2.適用於所有二叉樹的儲存(鏈式儲存結構) 我們可以如下定義: _________________ |Lchild | Data |Rchild| 描述如下:
typedef struct同樣當我們需要父母時也可以加上parent,組成三叉連結串列node{ int data; struct node* Lchild; struct node* Rchild; }sitnode,*Sitree;
二叉樹的遍歷: 1.遞迴實現: A、先序遍歷:root->left->right B、中序遍歷:left->root->right C、後序遍歷:right->left->root
void FreOrder(Bitree root) { if(root) { Visit(root->data); FreOrder(root->Lchild); FreOrder(root->Rchild); } }//中序遍歷和後序遍歷只是修改順序
2.非遞迴實現 先序遍歷的實現: 1)訪問root,root入棧並進入其左子樹,進而訪問左子樹的root併入棧,在進入下一層左子樹,...直到為空 2)棧非空則從棧頂退出上一層的結點,並進入該節點的右子樹
1 void PreOrder(Bitree root){ 2 Seqstack *s; 3 Bitree p; 4 InitStack(S); 5 p=root; 6 while(p!=NULL||!IsEmpty(s)) 7 { 8 while(p!=NULL) 9 { 10 Visit(p->data); 11 Push(S,p); 12 p=p->Lchild; 13 } 14 if(!IsEmpty(S)){ 15 Pop(S,p); 16 p=p->Rchild; 17 } 18 } 19 }中序遍歷只是調換了data的訪問位置
後序遍歷: 1.當前結點進棧,並進入其左子樹,重複至當前結點為空; 2.若棧非空,判斷棧頂結點P的右子樹是否為空,右子樹是否訪問過,是則退棧
1 void PostOrder(Bitree root) 2 { 3 SeqStack *s; 4 Sitree p,q; 5 InitStack(s); 6 p=root; 7 q=NULL; 8 while(p!=NULL||!IsEmpty(S)) 9 { 10 while(p!=NULL); 11 { 12 push(s,p); 13 p=p->Lchild; 14 } 15 if(!IsEmpty(s)) 16 { 17 Top(s,&p); 18 if((p->Rchild==NULL)||(p->Rchild==q)) 19 { 20 Pop(s,p); 21 Visit(P->data); 22 q=p; 23 p=NULL; 24 } 25 else 26 p = p-> Rchild; 27 } 28 } 29 30 }
//以上是我用一小時對二叉樹的複習,其中運用棧的地方,讀者可以自行定義變化。
上面僅是博主的自己複習的內容,如果有用,感謝支援,如有不足,請大佬指正!