一、二叉樹的性質
- 二叉樹的第i層上最多有2i-1個結點(i≥1)。
- 深度爲k的二叉樹最多有2k-1個結點(k≥1 )
- 一棵非空二叉樹,若葉子結點數爲n0,度數爲2的結點數爲n2,則n0=n2+1。
1.1 完全二叉樹特有性質
- 具有n個結點的完全二叉樹的深度必爲log2n+1
- 對於具有n個結點的完全二叉樹,如果按照從上到下和從左到右的順序對二叉樹中的所有結點從1開始順序編號,則對於任意的序號爲i的結點有如下性質:
- 對於具有n個結點的完全二叉樹,如果按照從上到下和從左到右的順序對二叉樹中的所有結點從1開始順序編號,則對於任意的序號爲i的結點有如下性質:
(1)如i=1,則序號爲i的結點是根結點,無雙親結點;如i>1,則序號爲i的結點的雙親結點序號爲i/2
(2)如2i>n,則序號爲i的結點無左孩子;如2i≤n,則序號爲i的結點的左孩子結點的序號爲2i
(3)如2i+1>n,則序號爲i的結點無右孩子;如2i+1≤n,則序號爲i的結點的右孩子結點的序號爲2i+1
1.2滿二叉樹特殊性質
- 深度爲k時,結點數n=2k-1
- 不存在度爲1的結點
- 每個結點都有兩棵高度相同的子樹
- 深度爲k的完全二叉樹,前k-1層構成一棵深度爲k-1的滿二叉樹
二、二叉樹的存儲
2.1順序存儲
不常用,侷限性比較大,不寫了。
2.2鏈式存儲
鏈表中每個結點由 三個區域組成:
名稱 | 意義 |
---|---|
data | 數據:存放節點的數據信息 |
lchild | 存放指向左孩子的指針 |
rchild | 存放指向右孩子的指針 |
結點數據類型定義:
typedef struct BiTNode{
DataType data;
structBiTNode *lchild, *rchild;
} BiTNode, *BiTree;
說明: 在n個結點的二叉鏈表中,有n+1個空指針域。 1
2.3二叉樹的遍歷
2.3.1 遍歷的方法
- 先序:DLR
- 中序:LDR
- 後序:LRD
- 層序遍歷:按二叉樹的層序編號的次序訪問各結點。
樹:二叉樹的層序遍歷算法(超簡潔實現及詳細分析)
先序:
若二叉樹爲空,則遍歷結束,否則依次執行如下3個操作:
1.訪問根結點
2.先序遍歷根結點的左子樹
3.先序遍歷根結點的右子樹
void PreOrder(BiTreebt)
/*先序遍歷二叉樹, bt爲指向二叉樹(或某一子樹)根結點的指針*/
{
if (bt==NULL)
return ;
Visit(bt->data); /*訪問根結點*/
PreOrder(bt->lchild); /*先序遍歷左子樹*/
PreOrder(bt->rchild); /*先序遍歷右子樹*/
}
中序:
若二叉樹爲空,則遍歷結束,否則依次執行如下3個操作:
1.中序遍歷根結點的左子樹
2.訪問根結點
3.中序遍歷根結點的右子樹
void InOrder(BiTreebt)
/*中序遍歷二叉樹, bt爲指向二叉樹(或某一子樹)根結點的指針*/
{
if (bt=NULL)
return ;
InOrder(bt->lchild); /*中序遍歷左子樹*/
Visit(bt->data); /*訪問根結點*/
InOrder(bt->rchild); /*中序遍歷右子樹*/
}
後序:
若二叉樹爲空,則遍歷結束,否則依次執行如下3個操作:
1.後序遍歷根結點左子樹
2.後序遍歷根結點右子樹
3.訪問根結點
void PostOrder(BiTreebt)
/*後序遍歷二叉樹, bt爲指向二叉樹(或某一子樹)根結點的指針*/
{
if (bt=NULL)
return ;
Post Order (bt->lchild); /*後序遍歷左子樹*/
PostOrder(bt->rchild); /*後序遍歷右子樹*/
Visit(bt->data); /*訪問根結點*/
}
小結
已知一棵二叉樹的先序序列和中序序列,構造該二叉樹的過程如下:
- 根據先序序列的第一個元素建立根結點;
- 在中序序列中找到該元素,確定根結點的左右子樹的中序序列;.
- 在先序序列中確定左右子樹的先序序列;
- 由左子樹的先序序列和中序序列建立左子樹;
- 由右子樹的先序序列和中序序列建立右子樹。
上機實驗報告代碼:
先序建立二叉樹,後序打印;
#include "stdio.h" //設數據域類型爲字符型
typedef struct node{
char data;
struct node *lchild,*rchild;
}BiTNode, *BiTree; //指向二叉樹結點的指針類型
void CreateBiTree(BiTree *t); //構造二叉鏈表
void PostOrder(BiTree p); //後序遍歷
void main( ) //主函數
{
BiTree T;
char ch1,ch2;
printf("\n請選擇:\n");
ch1='y';
while(ch1=='y'||ch1=='Y')
{
printf("\n1------------------二叉樹建立-------------");
printf("\n2------------------後序遍歷---------------");
printf("\n3------------------退出-------------------\n");
scanf("\n%c",&ch2);
switch(ch2)
{
case '1':printf("請按先序輸入建立二叉樹存儲的結點序列:\n");
CreateBiTree(&T);
break;
case '2':printf("該二叉樹的後序遍歷序列爲:\n"); //調用後序遍歷函數
PostOrder(T);
break;
case '3':printf("Thank you.\n");
ch1 = 'n';
break;
default: printf("輸入有誤,請重新選擇");
}
}
}
void CreateBiTree( BiTree *t) //構造二叉鏈表
{
char ch;
scanf("\n%c",&ch);
if(ch=='0') *t=NULL; //讀入0時,將相應結點置空
else
{
*t=new BiTNode; //生成結點空間
(*t)->data=ch;
CreateBiTree(&(*t)->lchild); //構造二叉樹的左子樹
CreateBiTree(&(*t)->rchild); //構造二叉樹的右子樹
}
}
void PostOrder(BiTree p) //後序遍歷
{
if(p != NULL)
{
PostOrder(p->lchild);
PostOrder(p->rchild);
printf(" %c",p->data);
}
}
全部的結點爲2n,其中被佔用n-1,所以2n-(n-1)=n+1; ↩︎