二叉樹
滿二叉樹和完全二叉樹
在一棵二叉樹中,如果所有的分支節點都有左孩子和右孩子,並且葉子節點都集中在二叉樹的最下一層,則這樣的二叉樹被稱爲滿二叉樹。
如果一棵深度爲k有n個節點的二叉樹進行編號後,各結點的編號與深度爲k的滿二叉樹中相同位置山的結點的編號軍相投,那麼這棵二叉樹就是一顆完全二叉樹。
二叉樹的性質
- 總分支數=總結點數-1(這條結論對任何樹都適用,不止是二叉樹) 證明:在二叉樹中除根節點之外,每一個結點都有唯一的一個分支指向它,由此可證。
- 非空二叉樹上葉子節點數等於雙分支節點數+1 證明:由上一條性質可證。設二叉樹葉子節點數爲n0,單分支節點數爲n1,雙分支節點數爲n2,則總結點數爲n0+n1+n2。總分支數爲2n2+n1。由上一條性質可得,n0+n1+n2-1=2n2+n1。 化簡得:n0=n2+1。(注意,這種證明方法常常被用到)
- 二叉樹的第i層上最多有2i-1(i>=1)個節點。
- 高度爲k的二叉樹最多有2k-1(K>=1)個節點。換句話說滿二叉樹中前k層的結點個數爲2k-1。 證明:等比數列求和問題。
- 有n個階段的完全二叉樹,對各節點從上到下,從左到右依次編號(編號範圍1~n),則節點之間有如下關係。 若i爲某節點a的編號,則: 如果i!=1,則雙親節點的編號爲i/2向下取整。 如果2i<=n,則左孩子的編號爲2i;如果2i>n,則a無左孩子。 如果2i+1<=n,則右孩子的編號爲2i+1;如果2i+1>n,則a無右孩子。
二叉樹的數據結構
二叉樹也有順序存儲結構和鏈式存儲結構。順序存儲結構是用數組存儲,下標遵循上面第5條性質,注意下標從1開始。鏈式存儲結構是最常用的存儲二叉樹的結構,如下圖所示。
其中data表示節點數據域,用與存儲對應的數據元素;lchild和rchild分別表示左指針域和右指針域,分別用於存儲左孩子結點和右孩子結點的位置。定義如下:
typedef struct BTNode
{
char data;
struct BTNode *lchild;
struct BTNode *rchild;
}BTNode
二叉樹的算法
二叉樹的算法主要是遍歷算法,包括
深度遍歷(先序遍歷,中序遍歷,後序遍歷)
廣度遍歷(層次遍歷)。這也是解大多數二叉樹題目的關鍵。
三種遍歷(先序遍歷,中序遍歷,後序遍歷)
ps:這裏不再贅述,直接書上介紹粘貼,字有點醜,湊合看吧哈哈~~
void PreOrderTraverse(BiTree T) //先序遍歷
{
if(T!=NULL)
{
cout<<T->data<<" ";
PreOrderTraverse(T->lchild);
PreOrderTraverse(T->rchild);
}
}
void InOrderTraverse(BiTree T) //中序遍歷
{
if(T!=NULL)
{
InOrderTraverse(T->lchild);
cout<<T->data<<" ";
InOrderTraverse(T->rchild);
}
}
void PostOrderTraverse(BiTree T) //後序遍歷
{
if(T!=NULL)
{
PostOrderTraverse(T->lchild);
PostOrderTraverse(T->rchild);
cout<<T->data<<" ";
}
}
層次遍歷的僞代碼如下:
根節點入隊
while(隊不空)
{
節點出隊,並訪問
if(左子樹不爲空)
左子樹入隊
if(右子樹不爲空)
右子樹入隊
}
c++代碼如下:
void LevelOrderTraverse()
{
int front=0,rear=0; //定義循環隊列
BiTNode *que[Maxsize];
front=rear;
BiTNode *q;
if(T!=NULL) //如果傳過來的樹不爲空
{
rear=(rear+1)%Maxsize;
que[rear]=T; //根節點入隊
while (front!=rear) //隊列不爲空
{
front=(front+1)%Maxsize;
q=que[front]; //隊頭出隊
cout<<q->data<<" "; //訪問隊頭
if (q->lchild!=NULL) //如果左子樹不空,則左子根入隊
{
rear=(rear+1)%Maxsize;
que[rear]=q->lchild;
}
if (q->rchild!=NULL) //如果右子樹不空,則右子根入隊
{
rear=(rear+1)%Maxsize;
que[rear]=q->rchild;
}
}
}
}
這4個算法,就像模板一樣,大多數的二叉樹題目只要會套這個模板就能解決,因此它非常重要。
二叉樹操作類:
class BinaryTreeOperator // 二叉樹操作類
{
public:
BiTree T;
BinaryTreeOperator()
{
InitBiTree();
}
~BinaryTreeOperator()
{
DestroyBitree(T);
}
void InitBiTree(); //初始化函數
BiTree CreatBitree(char *str1,char*str2,int i,int j,int k,int l); //根據先序和後序遍歷結果建立二叉樹
void DestroyBitree(BiTree T); //銷燬二叉樹函數
void PreOrderTraverse(BiTree T); //遞歸先序遍歷
void InOrderTraverse(BiTree T); //遞歸中序遍歷
void PostOrderTraverse(BiTree T); //遞歸後序遍歷
void NOPreOrder(); //非遞歸先序遍歷
void NOInOrder(); //非遞歸中序遍歷
void NOPostOrder(); //非遞歸後序遍歷
void LevelOrderTraverse(); //層次遍歷
void display(BiTree T); //按二叉樹形態遍歷輸出
int BiTreeDepth(BiTree T); //求二叉樹的深度
void computelayer(); //標記二叉樹的層數
int lush();
void CountLeaf(BiTree T,int &num); //數葉子
void Exchange(BiTree T); //交換左右子樹
void JudgeTree(); //判斷一棵是否爲完全二叉樹
};
其他參考:http://www.jinrongtong5.com/article/9#