數據結構二叉樹的基本操作的實現

一、實驗目的

(1)掌握二叉樹的邏輯結構;
(2)掌握二叉樹的二叉鏈表存儲結構;
(3)掌握基於二叉鏈表存儲的二叉樹的遍歷操作的實現。

二、實驗內容

(1)建立一棵含有n個結點的二叉樹,採用二叉鏈表存儲;
(2)前序(或中序、後序)遍歷該二叉樹。
(3)統計該二叉樹中葉子個數。
(4)統計該二叉樹中結點個數。
(5)求該二叉樹的深度。
要求:
(1)設計菜單,根據菜單提示進行操作。
(2)按先序遍歷序列創建二叉樹的二叉鏈表。
注:二叉樹的遍歷一般採用遞歸算法,只要涉及到遞歸,一定會使用堆棧來實現。雖然在程序中看不到具體的堆棧,但可以通過觀察函數調用的關係來理解認識堆棧。堆棧是實現二叉樹遍歷的最基本的數據結構。

三、算法設計

1、先序遍歷遞歸建立二叉樹

步驟

  1. 掃描字符序列, 讀入字符ch
  2. 如果ch是一個 "#" 字符, 則表明該二叉樹爲空樹, 即BTNULL; 3. 否則執行以下操作:
    申請一個結點空間BT;
    ch賦給BT-> data;
    遞歸創建BT的左子樹;
    遞歸創建BT的右子樹;

算法

void CreateBiTree(BiTree &BT){
	if(ch=='#')
	     BT = NULL;
	else{
       BT = new BiTNode;
       BT->data = ch;
       CreateBiTree (BT->Lchild);
       CreateBiTree (BT->Rchild);
	}
}
2、遍歷二叉樹
2.1 先序遍歷

步驟
若二叉樹爲空,則空操作;
否則 :

  1. 訪問根結點;
  2. 先序遍歷左子樹;
  3. 先序遍歷右子樹

算法

void PreOrder(BiTree &BT){
	if(BT){
        Visit(BT);
        PreOrder(BT->Lchild);
        PreOrder(BT->Rchild);
     }
}
2.2 中序遍歷

步驟
若二叉樹爲空,則空操作;
否則

  1. 中序遍歷左子樹;
  2. 訪問根結點;
  3. 中序遍歷右子樹。
    算法
void InOrder(BiTree BT){
    if(BT){
        InOrder(BT->Lchild);
        Visit(BT);
        InOrder(BT->Rchild);
    }
}
2.3 後序遍歷

步驟
若二叉樹爲空,則空操作;
否則

  1. 後序遍歷左子樹;
  2. 後序遍歷右子樹;
  3. 訪問根結點。

算法

void PostOrder(BiTree BT){
    if(BT){
        PostOrder(BT->Lchild);
        PostOrder(BT->Rchild);
        Visit(BT);
    }
}
3、統計二叉樹葉子結點個數

步驟

  • 如果是空樹,則結點個數爲 0;
  • 如果只有根結點則就1個葉子結點;
  • 否則,結點個數爲左子樹的葉子結點個數加上右子樹的葉子結點個數。

算法

int LeafCount(BiTree &BT){
    if(!BT)
        return ERROR;
    if(!BT->Lchild&&!BT->Rchild)
        return OK;
    return(LeafCount(BT->Lchild)+LeafCount(BT->Rchild));
}
4、交換二叉樹左右子樹

算法

void ChangeLR(BiTree BT){
    BiTree St;
    if(BT){
        ChangeLR(BT->Lchild);
        ChangeLR(BT->Rchild);
        St = BT->Lchild;
        BT->Lchild = BT->Rchild;
        BT->Rchild = St;
    }
}
5、統計二叉樹中結點的總數

步驟

  • 如果是空樹,則結點個數爲 0;
  • 否則,結點個數爲左子樹的結點個數加上右子樹的結點個數再加上 1 。

算法

int NodeCount(BiTree BT){
    if(!BT)
        return ERROR;
	else
    	return(NodeCount(BT->Lchild)+NodeCount(BT->Rchild)+1);
}
6、求二叉樹的深度

步驟
如果是空樹,遞歸結束,深度爲0;
否則執行以下操作:

  • 遞歸計算左子樹的深度記爲m;
  • 遞歸計算右子樹的深度記爲n;
  • 如果 m 大於 n, 二叉樹的深度爲 m+1, 否則爲 n+1。

算法

int Depth(BiTree BT){
    int h1,h2;
    if(BT==NULL)
        return ERROR;
    h1 = Depth(BT->Lchild);
    h2 = Depth(BT->Rchild);
    if(h1>h2)
        return(h1 + 1);
    else
        return(h2 + 1);
}

四、運行結果

在這裏插入圖片描述

五、代碼實現

#include<stdio.h>
#include<stdlib.h>
#define ERROR 0
#define OK 1
#define TElemType char
typedef struct BiTNode{
    TElemType data;
    struct BiTNode *Lchild,*Rchild;
}BiTNode,*BiTree;

//顯示根結點
void Visit(BiTree BT){
    printf("%c",BT->data);
}

//先序遍歷
void PreOrder(BiTree BT){
    if(BT){
        Visit(BT);
        PreOrder(BT->Lchild);
        PreOrder(BT->Rchild);
    }
}

//中序遍歷
void InOrder(BiTree BT){
    if(BT){
        InOrder(BT->Lchild);
        Visit(BT);
        InOrder(BT->Rchild);
    }
}

//後序遍歷
void PostOrder(BiTree BT){
    if(BT){
        PostOrder(BT->Lchild);
        PostOrder(BT->Rchild);
        Visit(BT);
    }
}

//按先序次序輸入二叉樹中結點的值(一個字符),創建二叉鏈表表示的二叉樹
void CreateBiTree(BiTree &BT){
    char ch;
	scanf("%c",&ch);
    if(ch!='#'){
    	BT =new BiTNode;
//    	if(!BT)
//			exit(-1);
        BT->data = ch;
        CreateBiTree(BT->Lchild);
        CreateBiTree(BT->Rchild);
	}
    else{
        BT = NULL;
    }
}

//統計二叉樹中葉子結點的個數
int LeafCount(BiTree &BT){
    if(!BT)
        return ERROR;
    if(!BT->Lchild&&!BT->Rchild)
        return OK;
    return(LeafCount(BT->Lchild)+LeafCount(BT->Rchild));
}

//交換二叉樹的左右子樹
void ChangeLR(BiTree BT){
    BiTree St;
    if(BT){
        ChangeLR(BT->Lchild);
        ChangeLR(BT->Rchild);
        St = BT->Lchild;
        BT->Lchild = BT->Rchild;
        BT->Rchild = St;
    }
}

//統計二叉樹中結點的總數
int NodeCount(BiTree BT){
    if(!BT)
        return ERROR;
	else
    	return(NodeCount(BT->Lchild)+NodeCount(BT->Rchild)+1);
}

//求二叉樹的深度
int Depth(BiTree BT){
    int h1,h2;
    if(BT==NULL)
        return ERROR;
    h1 = Depth(BT->Lchild);
    h2 = Depth(BT->Rchild);
    if(h1>h2)
        return(h1 + 1);
    else
        return(h2 + 1);
}

//銷燬二叉樹
void DestroyBiTree(BiTree BT){
    if(!BT)return;
    DestroyBiTree(BT->Lchild);
    DestroyBiTree(BT->Rchild);
    delete BT;
}

void Showmenu(){
    printf("\n");
    printf("     --二叉樹基本操作運算--    \n");
    printf("******************************\n");
    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("*     0---退出               *\n");
    printf("*****************************\n");
    printf("請選擇菜單號(0-8):");
}

void binaryOP(){
    BiTree BT;
    int count = 0;
    int choice;
    while(choice){
        Showmenu();
        scanf("%d",&choice);
        switch(choice){
            case 1:
                printf("按先序輸入二叉樹結點序列:\n");//以#結束
                CreateBiTree(BT);
                printf("二叉樹建立成功!\n");
                break;
            case 2:
                if(BT == NULL){
                    printf("空樹!\n");
                }
                else{
                    printf("先序遍歷序列爲:");
                    PreOrder(BT);
                }
                break;
            case 3:
                if(BT == NULL){
                    printf("空樹!\n");
                }
                else{
                    printf("中序遍歷序列爲:");
                    InOrder(BT);
                }
                break;
            case 4:
                if(BT == NULL){
                    printf("空樹!\n");
                }
                else{
                    printf("後序遍歷序列爲:");
                    PostOrder(BT);
                }
                break;
            case 5:
                count = LeafCount(BT);
                printf("該二叉樹有%d個葉子結點。\n",count);
                break;
            case 6:
                count = NodeCount(BT);
                printf("該二叉樹有%d個結點。\n",count);
                break;
            case 7:
                printf("該二叉樹的深度爲%d !\n",Depth(BT));
                break;
            case 8:
                ChangeLR(BT);
                printf("交換成功!\n");
                printf("先序序列爲:\n");
                PreOrder(BT);
                break;
            case 0:
                printf("程序結束!\n");
                break;
        }
    }
}

int main(){
    binaryOP();
    return 0;
}

作者文壇寫於 2020年5月21日

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章