二叉樹實驗報告
實驗報告
實驗題目:二叉樹
實驗目的:
1、熟悉二叉樹的結點型別和二叉樹的基本操作。
2、掌握二叉樹的前序、中序和後序遍歷的演算法。
3、加深對二叉樹的理解,逐步培養解決實際問題的程式設計能力。
基本要求:
1.編寫程式bitree.cpp實現ADTBiTree,要求使用二叉連結串列儲存。實現基本操作:
InitBiTree(&T);
DestroyBiTree(&T);
PreOrder(T,visit());
InOrder(T,visit());
PostOrder(T,visit());
2.編碼實現以下演算法:
1)建立二叉樹。(以先序擴充套件序列給出)
2)輸出先序、中序和後序序列。
3)計算二叉樹結點數、葉子結點數、高度。
測試資料:先序擴充套件序列:ABDF##G##E#H##C##輸出:先序ABDFGEHC中序FDGBEHAC後序FGDHEBCA結點數:8葉子結點數:4高度:4。
實驗拓展
1)實現層次遍歷。
2)查詢:查值為X的結點、雙親結點、孩子結點、兄弟結點
3)判斷:判斷一個二叉樹是否為二叉排序樹、完全二叉樹、平衡和二叉樹
4)處理:左右子樹互換、複製、刪除子樹、插入子樹
設計思路:
1. 在二叉樹的儲存結構為鏈式儲存結構。
2. 在具體實現的時候建立不同函式,在主程式中用迴圈選單的形式呼叫函式提高了效率。
概要分析:
二叉連結串列結構定義:
typedef struct BiNode{
ElemType data;
struct BiNode *lchild,*rchild;
}BiNode,*BiTree;
CreatBiTree(BiTree &T);先序建立二叉樹。
DestroyBiTree(BiTree &T);銷燬二叉樹;
PreOrder(BiTree &T);先序遍歷二叉樹
InOrder(BiTree &T);中序遍歷二叉樹
PostOrder (BiTree &T);後序遍歷二叉樹
PrintbyLev(BiTree &T);按層次遍歷二叉樹,利用佇列的思想,從根結點開始將其放入一個數組中,用i記錄子節點尚未放入陣列的位置,再將i所指向節點的左右節點放入佇列中,然後i+1,對下一個節點這樣操作,直至最後一個節點是葉子節點。
IsLeaf(BiTree &T);判斷是否為葉子節點(是否有左右子樹)。
FullBiTree(BiTree &T);判斷是否為完全二叉樹,採用廣度優先遍歷,從根節點開始,入佇列,如果佇列不為空,迴圈。遇到第一個沒有左兒子或者右兒子的節點,設定標誌位,如果之後再遇到有左/右兒子的節點,那麼這不是一顆完全二叉樹。
CountBiTree(BiTree &T);節點計數,用遞迴思想,對左右子樹計數,再加起來。
LevelNum(BiTree& T,int t,int d);計算層數,利用遞迴思想,對左右子樹計算層數並取較大值。
LeafNum(BiTree& T,int t,int d,int ln);葉子節點計數,利用遞迴思想,計算左右子樹葉子再計算和。
Balance(BiTree &T,int i);判斷是否為平衡二叉樹,遞迴判斷左右是否為平衡二叉樹(有層數記錄)。
Sort(BiTree &T,int i);判斷是否為二叉排序樹,判斷此節點是否滿足排序樹定義,在判斷其左右子樹是否滿足。
PrintChild(BiTree &T);列印左右子樹。
FindNode(ElemType x,BiTree &T);查詢演算法,如果是根節點提示是根節點並返回指向根節點的指標,若果不是則呼叫Findx函式。
FindX(ElemType x,BiTree &temp,BiTree &T);查詢演算法,返回指向對應子樹的根節點的指標。
CopyBiT(BiTree &T,BiTree &C);複製子樹。
執行截圖:
主介面
建立二叉樹
輸出三序遍歷及二叉樹資訊
按層輸出
查詢二叉樹
分析二叉樹
左右子樹互換:對A 然後按層次輸出
刪除以B為根節點的子樹:
(層次遍歷)
複製節點C
增加節點B於A的左節點
(層次遍歷)
結果與討論:
程式完成情況較好,由於實驗內容比較多,所以寫了很多函式,但有些函式之間是有呼叫關係,減輕了工作量。同時利用迴圈選單也讓程式看起來更為簡潔,呼叫子程式也更為方便。
程式程式碼:
include
include
include
include
define OK 1
define ERROR 0
//先序遍歷建立二叉樹
Status CreatBiTree(BiTree &T){
ElemType c;
cin >> c;
if(c==’.’){
T=NULL;
}
else{
T=(BiNode*)malloc(sizeof(BiNode));
T->data=c;
CreatBiTree(T->lchild);
CreatBiTree(T->rchild);
}
return 1;
}
Status DestroyBiTree(BiTree &T){
if(!T) return 1;
else{
DestroyBiTree(T->lchild);
DestroyBiTree(T->rchild);
free(T);
T=NULL;
return 1;
}
}
Status PreOrder(BiTree &T){
if(T){
printf(“%c”,T->data);
if(PreOrder(T->lchild))
if(PreOrder(T->rchild)) return 1;
return 0;
}
else return 1;
}
Status InOrder(BiTree &T){
if(T){
InOrder(T->lchild);
printf(“%c”,T->data);
InOrder(T->rchild);
return 1;
}
else return 1;
}
Status PostOrder(BiTree &T){
if(T){
PostOrder(T->lchild);
PostOrder(T->rchild);
printf(“%c”,T->data);
}
return 1;
}
//按層輸出
Status PrintbyLev(BiTree &T){
int i=0;
BiTree node[100];
int nn=1;
for(i=0;i<100;i++) node[i]=NULL;
node[0]=T;
i=0;
while(node[i]){
if(node[i]->lchild){
node[nn]=node[i]->lchild;
nn++;
}
if(node[i]->rchild){
node[nn]=node[i]->rchild;
nn++;
}
i++;
}
//CreatQueue(T);
for(i=0;node[i];i++){
printf(“%c”,node[i]->data);
}
printf(“\n”);
return 1;
}
int IsLeaf(BiTree &T){
if(T->lchild==NULL&&T->rchild==NULL) return 1;//葉子節點
else if(!T->lchild&&T->rchild) return 2;//有右無左
else if(!T->rchild&&T->lchild) return 3;//有左無右
else return 0; //有左有右
}
Status FullBiTree(BiTree &T){
int i=0,j=0;
BiTree node[100];
int nn=1;
for(i=0;i<100;i++) node[i]=NULL;
node[0]=T;
i=0;
while(node[i]){
if(node[i]->lchild){
node[nn]=node[i]->lchild;
nn++;
}
if(node[i]->rchild){
node[nn]=node[i]->rchild;
nn++;
}
i++;
}
i=0;
while(node[i]){
if(IsLeaf(node[i])==2) return 0;
i++;
}
while(IsLeaf(node[j])==0){
j++;
printf("*");
}
//j++;指標停在非左右子樹都存在的節點的下一位
if(IsLeaf(node[j])==3||IsLeaf(node[j])==1) j++;
while(node[j]!=NULL){
if(IsLeaf(node[j])!=1) return 0;
j++;
printf("*");
}
return 1;
}
//計數
int CountBiTree(BiTree &T){
int m,n;
if(T){
m=CountBiTree(T->lchild);
n=CountBiTree(T->rchild );
return m+n+1;
}
else return 0;
}
//層數
int LevelNum(BiTree& T,int t,int d){
if(t>d) d=t;
if(!T) return 0;
if (T->lchild) {
d=LevelNum(T->lchild,t+1,d);
}
if (T->rchild) {
d=LevelNum(T->rchild,t+1,d);
}
return d;
}
//葉子節點計數
int LeafNum(BiTree& T,int t,int d,int ln){
if(t==d) ln++;
if(!T) return 0;
if (T->lchild) {
ln=LevelNum(T->lchild,t+1,ln);
}
if (T->rchild) {
ln=LevelNum(T->rchild,t+1,ln);
}
return ln;
}
//判斷平衡
int Balance(BiTree &T,int i){
if (i==0) return i;
if (!T) return i;
if (abs(CountBiTree(T->lchild)-CountBiTree(T->rchild))>1){
i=0;return 0;
}
else {
Balance(T->lchild,i);
Balance(T->rchild,i);
}
return i;
}
//判斷二叉排序樹
int Sort(BiTree &T,int i){
if (i==0) return 0;
if(!T) return i;
if(T->lchild){
if (T->datalchild->data) return 0;
i=Sort(T->lchild,i);
}
else if (T->rchild){
if (T->datarchild->data) return 0;
i=Sort(T->rchild,i);
}
return i;
}
void judge(BiTree &T){
if(FullBiTree(T))
printf(“是完全二叉樹\n”);
if(Balance(T,1))
printf(“是平衡二叉樹\n”);
if(Sort(T,1))
printf(“是二叉排序樹\n”);
}
//列印子樹
void PrintChild(BiTree &T){
if(!T->lchild) printf(“此節點無左子樹\n”);
else printf(“左子樹為:%c\n”,T->lchild->data);
if(!T->rchild) printf(“此節點無右子樹\n”);
else printf(“右子樹為:%c\n”,T->rchild->data);
}
BiTree FindX(ElemType x,BiTree &temp,BiTree &T){
if (temp!=NULL||T==NULL) return temp;
if (T->lchild){
if (T->lchild->data==x)
return T;
else {
temp=FindX(x,temp,T->lchild);
temp=FindX(x,temp,T->rchild);
if(temp) return temp;
}
}
if (T->rchild){
//printf("**");
if (T->rchild->data==x)
return T;
else {
temp=FindX(x,temp,T->rchild);
temp=FindX(x,temp,T->lchild);
if(temp) return temp;
}
}
return temp;
}
//找X節點
BiTree FindNode(ElemType x,BiTree &T){
if(T->data==x){
printf("所找節點為根節點\n");
PrintChild(T);
return T;
}
BiTree Q=NULL;
Q=FindX(x,Q,T);
if(Q){
printf("其雙親節點為:%c\n",Q->data);
if(Q->lchild&&Q->lchild->data==x) {
if (!Q->rchild) printf("其無兄弟節點\n");
else printf("兄弟節點為%c\n",Q->rchild->data);
PrintChild(Q->lchild);
//return Q->lchild;
}
else{
if (!Q->lchild) printf("其無兄弟節點\n");
else printf("兄弟節點為%c\n",Q->lchild->data);
PrintChild(Q->rchild);
//return Q->rchild;
}
}
return Q;
}
//三序輸出
void printBiTree(BiTree &T){
int d,Ln,n;
PreOrder(T);
printf(“\n”);
InOrder(T);
printf(“\n”);
PostOrder(T);
printf(“\n”);
n=CountBiTree(T);
printf(“節點數為:%d\n”,n);
d=LevelNum(T,1,1);
printf(“深度為:%d\n”,d);
Ln=LeafNum(T,1,d,0);
printf(“葉子節點個數為:%d\n”,Ln);
}
Status CopyBiT(BiTree &T,BiTree &C){
if(!T) C=NULL;
else{
C=(BiNode*)malloc(sizeof(BiNode));
C->data=T->data;
//C->lchild=T->lchild;
//C->rchild=T->rchild;
CopyBiT(T->lchild,C->lchild);
CopyBiT(T->rchild,C->rchild);
}
return 1;
}
int main()
{
BiTree T,x,temp,temp1;
int d,Ln,n,j=1;
ElemType c;
while(j){
printf(“1.建立二叉樹\n”);
printf(“2.前中後序輸出二叉樹\n”);
printf(“3.按層輸出二叉樹\n”);
printf(“4.查詢二叉樹\n”);
printf(“5.分析二叉樹\n”);
printf(“6.左右子樹互換\n”);
printf(“7.刪除子樹\n”);
printf(“8.複製子樹\n”);
printf(“9.增加子樹\n”);
scanf(“%d”,&j);
switch(j){
case 1: CreatBiTree(T);break;
case 2: printBiTree(T);break;
case 3: PrintbyLev(T); break;
case 4:
printf(“請輸入要查詢節點:\n”);
getchar();
scanf(“%c”,&c);
x=FindNode(c,T);
break;
case 5:judge(T);break;
case 6:
printf(“輸入根節點:\n”);
getchar();
scanf(“%c”,&c);
if(c==T->data){
x=T;
temp=x->lchild;
x->lchild=x->rchild;
x->rchild=temp;
PrintChild(T);
break;
}
x=FindNode(c,T);
if(x->lchild&&x->lchild->data==c){
x=x->lchild;
//x->lchild=NULL;
}
else if(x->rchild&&x->rchild->data==c) {
x=x->rchild;
// x->rchild=NULL;
}
temp=x->lchild;
x->lchild=x->rchild;
x->rchild=temp;
printf("交換之後:\n");
PrintChild(x);
break;
case 7:
printf("輸入根節點:\n");
getchar();
scanf("%c",&c);
if(T->data==c){
x=T;
}
else{
x=FindNode(c,T);
}
if(x->lchild&&x->lchild->data==c){
temp=x->lchild;
x->lchild=NULL;
}
else if(x->rchild&&x->rchild->data==c) {
temp=x->rchild;
x->rchild=NULL;
}
//printBiTree(x);
DestroyBiTree(temp);
break;
//x=NULL;
case 8:
printf("輸入根節點:\n");
getchar();
scanf("%c",&c);
x=FindNode(c,T);
if(x->lchild&&x->lchild->data==c){
temp=x->lchild;
}
else if(x->rchild&&x->rchild->data==c) {
temp=x->rchild;
// x->rchild=NULL;
}
CopyBiT(temp,temp1);
printBiTree(temp1);
break;
case 9:
printf("輸入要插入的子樹:\n");
CreatBiTree(temp1);
printf("輸入插入根節點:\n");
getchar();
scanf("%c",&c);
if(T->data==c){
temp=T;
}
else{
x=FindNode(c,T);
if(x->lchild&&x->lchild->data==c){
temp=x->lchild;
}
else if(x->rchild&&x->rchild->data==c) {
temp=x->rchild;
}
}
printf("1.左子樹 2.右子樹\n");
scanf("%d",&d);
if(d==1) temp->lchild=temp1;
else temp->rchild=temp1;
//printBiTree(T);
}
}
}