【筆記】遍歷二叉樹的應用
1.二叉樹的計數
二叉樹的計數也可以通過遍歷二叉樹來實現,關於二叉樹計數的演算法有求二叉樹葉子節點的個數、非葉子節點的個數。
- 計算二叉樹葉子結點個數
求二叉樹的葉子節點的個數遞迴定義如下。
當二叉樹為空時,葉子節點個數為0;當二叉樹只有一個根節點時,根節點就是葉子節點,葉子節點個數為1;其他情況下,計算左子樹與右子樹中葉子節點的和。由此可得到統計葉子節點個數的演算法。
int LeafCount(BiTree T)
/*統計二叉樹中葉子結點數目*/
{
if(!T) /*如果是空二叉樹,返回0*/
return 0;
else
if(!T->lchild&&!T->rchild) /*如果左子樹和右子樹都為空,返回1*/
return 1;
else
return LeafCount(T->lchild)+LeafCount(T->rchild); /*將左子樹葉子結點個數與右子樹葉子結點個數相加*/
}
- 求二叉樹的非葉子節點個數
二叉樹的非葉子節點的個數的遞迴定義如下:
當二叉樹為空時,非葉子結點的個數為0;當二叉樹只有根節點時,根節點為葉子結點,非葉子節點個數為0;其他情況下,非葉子結點個數為左子樹與右子樹中非葉子節點的個數再加1(根結點)。
int NotLeafCount(BiTree T)
/*統計二叉樹中非葉子結點數目*/
{
if(!T) /*如果是空二叉樹,返回0*/
return 0;
else if(!T->lchild&&!T->rchild) /*如果是葉子結點,返回0*/
return 0;
else
return NotLeafCount(T->lchild)+NotLeafCount(T->rchild)+1; /*左右子樹的非葉子結點數目加上根結點的個數*/
}
- 計算二叉樹的所有結點數
二叉樹的所有結點的個數的遞迴定義如下:
若二叉樹為空,則結點個數為0;在二叉樹不為空的情況下,若左、右子樹為空,則結點數為1;否則, 二叉樹的結點數為左、右子樹的結點數之和加1。
int AllNodes(BiTree T)
/*求二叉樹中所有結點的個數*/
{
if(!T) /*如果是空二叉樹返回0*/
return 0;
else if(!T->lchild&&!T->lchild)/*如果是葉子結點返回1*/
return 1;
else /*如果是非葉子節點,也不是根節點*/
return AllNodes(T->lchild)+AllNodes(T->rchild)+1;/*左右子樹結點個數加根節點個數*/
}
- 計算二叉樹的深度
二叉樹的深度遞迴定義如下:
當二叉樹為空時,其深度為0;當二叉樹只有根節點時,即結點的左、右子樹均為空時,二叉樹的深度為1;在其他情況下,求二叉樹的左、右子樹的最大值再加1(根節點)。由此,得到二叉樹的深度的演算法如下:
int BitTreeDepth(BiTree T)
/*計算二叉樹的深度*/
{
if(T == NULL)
return 0;
return
BitTreeDepth(T->lchild)>BitTreeDepth(T->rchild)?1+BitTreeDepth(T->lchild):1+BitTreeDepth(T->rchild);
}
2.求葉子節點的最大最小枝長
求二叉樹的所有葉子節點的最大枝長的遞迴模型如下:
求二叉樹的所有葉子節點的最小枝長的遞迴模型如下:
void MaxMinLeaf(BitTree T,int *max,int *min)
{
int m1,m2,n1,n2;
if(T==NULL)
{
*max=0;
*min=0;
}
else
{
MaxMinLeaf(T->lchild,m1,n1);
MaxMinLeaf(T->rchild,m2,n2);
*max=(m1>m2?m1:m2)+1;
*min=(m1<m2?m1:m2)+1;
}
}
3.判斷兩顆二叉樹是否相似
兩顆二叉樹相似的定義:或者
判斷兩顆二叉樹是否相似可在用同樣的次序遍歷這兩顆二叉樹的過程中進行,因此可用遞迴演算法實現。設t1和t2分別是指向二叉樹
int BiTree_Like(BiTree t1,BiTree t2)
{
if(t1==NULL && t2==NULL)
return 1;
if((t1!=NULL && t2==NULL)||(t1==NULL && t2!=NULL))
return 0;
if(BiTree_Like(t1->rchild,t2->rchild))
/*若左子樹相似*/
return (BiTree_Like(t1->rchild,t2->rchild))
else
return 0;
}
4.交換二叉樹的左右子樹
同樣,在遍歷二叉樹的過程中也可以交換各個結點的左右子樹。
void Bitree_Swap(BiTree T)
{
BiTree p;
if(!T=NULL)
if(T->lchild!=NULL||T->rchild!=NULL)
{
p=T->rchild;
T->lchild=T->rchild;
T->rchild=p;
}
if(T->lchild!=NULL)/*若T的左子樹不為空,則將左右子樹交換*/
Bitree_Swap(T->lchild);
if(T->rchild!=NULL)/*若T的右子樹不為空,則將左右子樹交換*/
Bitree_Swap(T->rchild);
}
也可以用後序遍歷的方式實現交換左右兩顆子樹,但不宜用中序遍歷的方式實現,因為若用中序遍歷的演算法,則僅交換了根節點的左右孩子。
5.求根節點到r結點之間的路徑
假設二叉樹採用二叉連結串列方式儲存,root指向根節點,r所指結點為任一結點。由於後序遍歷的過程中,訪問到r所指結點時,此時棧中所有結點均為r所指的祖先,這些祖先便構成了一條從根節點到r所指結點之間的路徑,故可採用後序遍歷。
void path(BiTree root,BitNode *r)
{
BitNode *p,*q;
int i ,top=0;
BitNode *s[StackSize];
q=NULl;
p=root;
while(p!=NULL||top!=0)
{
while(p!NULL)
/*遍歷左子樹*/
{
top++;
if(top>=StackSize)
exit(-1);
s[top]=p;
p=p->lchild;
}
if(top>0)/*若棧不為空*/
{
p=s[top];
if(p->lchild == NULL ||p->rchild==q)/*根節點*/
{
if(p==r)/*找到r所指結點,則輸出從根節點到r所指結點之間的結點*/
{
for(i=1;i<=top;i++)
{
printf("%4d",s[i]->data);
top=0;
}
}
else
{
q=p;/*用q儲存剛剛遍歷過的結點*/
top--;
p=NULL;
}
}
else
p=p->rchild;/*遍歷右子樹*/
}
}
}
相關文章
- 二叉樹的遍歷筆記二叉樹筆記
- 二叉樹的遍歷及應用二叉樹
- 二叉樹的遍歷二叉樹
- 二叉樹---遍歷二叉樹
- 二叉樹遍歷二叉樹
- 完全二叉樹的遍歷二叉樹
- 玩轉二叉樹(樹的遍歷)二叉樹
- 二叉樹的廣度遍歷和深度遍歷()二叉樹
- 二叉樹遍歷方法二叉樹
- 二叉樹遍歷 -- JAVA二叉樹Java
- JAVA遍歷二叉樹Java二叉樹
- 二叉樹的建立、前序遍歷、中序遍歷、後序遍歷二叉樹
- 144.二叉樹的前序遍歷145.二叉樹的後序遍歷 94.二叉樹的中序遍歷二叉樹
- C++樹——遍歷二叉樹C++二叉樹
- 根據二叉樹的前序遍歷和中序遍歷輸出二叉樹;二叉樹
- 二叉樹的遍歷實現二叉樹
- 二叉樹的層序遍歷二叉樹
- 二叉樹的按層遍歷二叉樹
- 【練習】二叉樹的遍歷二叉樹
- 二叉樹的建立與遍歷二叉樹
- UVA 536 二叉樹的遍歷二叉樹
- 線索二叉樹【定義、應用、線索化、遍歷】二叉樹
- 迴圈遍歷二叉樹二叉樹
- 二叉樹四種遍歷二叉樹
- 二叉樹--後序遍歷二叉樹
- 層序遍歷二叉樹二叉樹
- 二叉樹建立,前序遍歷,中序遍歷,後序遍歷 思路二叉樹
- 二叉樹的遍歷 → 不用遞迴,還能遍歷嗎二叉樹遞迴
- 採用層次遍歷判斷二叉樹為完全二叉樹二叉樹
- 二叉樹的遍歷 (迭代法)二叉樹
- 二叉樹的構造與遍歷二叉樹
- 面試中很值得聊的二叉樹遍歷方法——Morris遍歷面試二叉樹
- 什麼是遍歷二叉樹,JavaScript實現二叉樹的遍歷(遞迴,非遞迴)二叉樹JavaScript遞迴
- 二叉樹遍歷方法總結二叉樹
- 二叉樹非遞迴遍歷二叉樹遞迴
- 6.14-二叉樹遍歷二叉樹
- 樹(2)--二叉樹的遍歷(非遞迴)+線索二叉樹二叉樹遞迴
- LintCode 前序遍歷和中序遍歷樹構造二叉樹二叉樹