目錄
(一)二叉樹圖文解析
本文章對遞歸的理解要求較高(反正我是說不清楚的=,=)
一般二叉樹採用的是鏈式存儲結構,也就是單鏈表的結構,但二叉樹的結點包括倆個指針域,一個指向左結點,一個指右結點,即二叉,就像樹木一樣分叉成倆根樹枝,直到樹木分叉到最後不再分叉,最後不再分叉的結點也就是樹木的葉子。
(二) 二叉樹代碼解析
(1)二叉樹的基本操作
1.1 二叉樹的存儲結構
typedef struct BiTNode
{
char data;//結點數據域
struct BiTNode *Lchild,*Rchild;//左指針和右指針
}BiTNode,*BiTree;
1.2 先序遍歷創建二叉樹
void CreatBiTree(BiTree &T)
{
char ch;
scanf("%c",&ch);//輸入結點數據
if(ch=='#')//輸入爲#代表結點爲空,不再創建新結點
T=NULL;
else
{
T=(BiTNode*)malloc(sizeof(BiTNode));//爲結點分配空間
T->data=ch;//結點數據域爲ch
CreatBiTree(T->Lchild);//遞歸創建左結點
CreatBiTree(T->Rchild);//遞歸創建右結點
}
}
1.3 二叉樹的先序遍歷
void PreOrderTraverse(BiTree T)
{
if(T)
{
printf("%c ",T->data);//先輸出當前結點的數據
PreOrderTraverse(T->Lchild);//然後遞歸遍歷左結點,輸出結點數據
PreOrderTraverse(T->Rchild);//再遞歸遍歷右結點,輸出結點數據
}
}
遍歷順序要根據函數內遞歸順序來:(強行解說遞歸,意會、意會…)
1、首先輸出當前結點數據,然後遞歸遍歷左結點,遞歸完左結點後再遞歸右結點;
2、遞歸左結點的過程中,依舊是先輸出當前結點數據,直到左結點爲空後結束遞歸
3、在遞歸完左結點後再遞歸完右結點,仍然是先輸出當前結點數據,直到有結點爲空後結束遞歸
1.4 二叉樹的中序遍歷
void InOrderTraverse(BiTree T)
{
if(T)
{
InOrderTraverse(T->Lchild);//先遞歸遍歷左結點,直到遞歸結束
printf("%c ",T->data);//在輸出數據
InOrderTraverse(T->Rchild);//然後遞歸遍歷右結點
}//先遍歷到最後一個左結點,再輸出數據,然後遍歷右結點
}
1.5 二叉樹的後序遍歷
void PostOrderTraverse(BiTree T)
{
if(T)
{
PostOrderTraverse(T->Lchild);//先遞歸遍歷左結點,直到結束
PostOrderTraverse(T->Rchild);//再遞歸遍歷右結點,直到結束
printf("%c ",T->data);//最後輸出數據
}//先遍歷到最後一個左結點,再遍歷到最後一個左結點的最後一個右結點,最後輸出數據
}
1.6 二叉樹的深度
int Depth(BiTree T)
{
if(T==NULL)
return 0;
else
{
int m=Depth(T->Lchild);//遞歸計算左子樹的深度
int n=Depth(T->Rchild);//遞歸計算右子樹的深度
if(m>n)//返回最大深度值
return m+1;
else
return n+1;
}
}
1.7 二叉樹的結點數
int NodeCount(BiTree T)
{
if(T==NULL)//結點爲空,遞歸結束
return 0;
else//返回左結點+右結點+1,[+1]相當於計數結點的數量
return NodeCount(T->Lchild)+NodeCount(T->Rchild)+1;
}
1.8 二叉樹的葉子數
int LeafCount(BiTree T)
{
if(T==NULL)
return 0;
else
if(!T->Lchild&&!T->Rchild)//單個結點沒有子結點,葉子數爲一
return 1;
else//遞歸計算左葉子數和右葉子數的總數
return LeafCount(T->Lchild)+LeafCount(T->Rchild);
}
(2) 二叉樹源代碼及測試
2.1 源代碼:
#include<stdio.h>
#include<malloc.h>
typedef struct BiTNode
{
char data;
struct BiTNode *Lchild,*Rchild;
}BiTNode,*BiTree;
void CreatBiTree(BiTree &T)
{
char ch;
scanf("%c",&ch);
if(ch=='#')
{
T=NULL;
}
else
{
T=(BiTNode*)malloc(sizeof(BiTNode));
T->data=ch;
CreatBiTree(T->Lchild);
CreatBiTree(T->Rchild);
}
}
void PreOrderTraverse(BiTree T)
{
if(T)
{
printf("%c ",T->data);
PreOrderTraverse(T->Lchild);
PreOrderTraverse(T->Rchild);
}
}
void InOrderTraverse(BiTree T)
{
if(T)
{
InOrderTraverse(T->Lchild);
printf("%c ",T->data);
InOrderTraverse(T->Rchild);
}
}
void PostOrderTraverse(BiTree T)
{
if(T)
{
PostOrderTraverse(T->Lchild);
PostOrderTraverse(T->Rchild);
printf("%c ",T->data);
}
}
int Depth(BiTree T)
{
if(T==NULL)
return 0;
else
{
int m=Depth(T->Lchild);
int n=Depth(T->Rchild);
if(m>n)
return m+1;
else
return n+1;
}
}
int NodeCount(BiTree T)
{
if(T==NULL)
return 0;
else
return NodeCount(T->Lchild)+NodeCount(T->Rchild)+1;
}
int LeafCount(BiTree T)
{
if(T==NULL)
return 0;
else
if(!T->Lchild&&!T->Rchild)
return 1;
else
return LeafCount(T->Lchild)+LeafCount(T->Rchild);
}
int main()
{
BiTree T;
printf("先序遍歷創建二叉樹\n輸入結點數據('#'結束):");
CreatBiTree(T);
printf("先序遍歷輸出:");
PreOrderTraverse(T);
printf("\n");
printf("中序遍歷輸出:");
InOrderTraverse(T);
printf("\n");
printf("後序遍歷輸出:");
PostOrderTraverse(T);
printf("\n");
printf("二叉樹深度:%d\n",Depth(T));
printf("二叉樹結點數:%d\n",NodeCount(T));
printf("二叉樹葉子數:%d\n",LeafCount(T));
return 0;
}
2.2 測試結果:
測試環境 : Windows 10
編譯軟件 : Visual C++ 6.0