StorageClass+nfs
阿新 • • 發佈:2020-11-05
二叉樹
這個作業屬於哪個課程 | https://edu.cnblogs.com/campus/qdu/DS2020 |
---|---|
這個作業要求在哪裡 | https://edu.cnblogs.com/campus/qdu/DS2020/homework/11430 |
這個作業的目標 | 掌握二叉樹的基本特性和二叉樹的先序、中序、後序的遞迴遍歷演算法,以及理解二叉樹的先序、中序、後序的非遞迴遍歷演算法 |
學號 | 2018204188 |
一.實驗目的
1.掌握二叉樹的基本特性
2.掌握二叉樹的先序、中序、後序的遞迴遍歷演算法
3.理解二叉樹的先序、中序、後序的非遞迴遍歷演算法
4.通過求二叉樹的深度、葉子結點數和層序遍歷等演算法,理解二叉樹的基本特性
二.實驗預習
說明以下概念
-
二叉樹:二叉樹作為樹形結構的一種,是每個節點最多有兩個子樹的樹結構。
-
遞迴遍歷:沿著某條搜尋路線,依次對樹(或圖)中每個節點均做一次訪問,遞迴作為遍歷的一種方法,是利用計算機的堆疊的概念,一般通過呼叫相同的函式來實現,函式中一般會設定終止的語句。
-
非遞迴遍歷:樹的遍歷若採用非遞迴的方法,就要採用棧去模擬實現。
-
層序遍歷:進行層序遍歷時,對某一層的節點訪問完後,再按照他們的訪問次序對各個節點的左孩子和右孩子順序訪問,這樣一層一層進行,先訪問的節點其左右孩子也要先訪問,這正好符合佇列的操作特性。
三.實驗內容和要求
1.閱讀並執行下面程式,根據輸入寫出執行結果,並畫出二叉樹的形態。
#include<stdio.h> #include<malloc.h> #define MAX 20 typedef struct BTNode{ /*節點結構宣告*/ char data ; /*節點資料*/ struct BTNode *lchild; struct BTNode *rchild ; /*指標*/ }*BiTree; void createBiTree(BiTree *t){ /* 先序遍歷建立二叉樹*/ char s; BiTree q; printf("\nplease input data:(exit for #)"); s=getche(); if(s=='#'){*t=NULL; return;} q=(BiTree)malloc(sizeof(struct BTNode)); if(q==NULL){printf("Memory alloc failure!"); exit(0);} q->data=s; *t=q; createBiTree(&q->lchild); /*遞迴建立左子樹*/ createBiTree(&q->rchild); /*遞迴建立右子樹*/ } void PreOrder(BiTree p){ /* 先序遍歷二叉樹*/ if ( p!= NULL ) { printf("%c", p->data); PreOrder( p->lchild ) ; PreOrder( p->rchild) ; } } void InOrder(BiTree p){ /* 中序遍歷二叉樹*/ if( p!= NULL ) { InOrder( p->lchild ) ; printf("%c", p->data); InOrder( p->rchild) ; } } void PostOrder(BiTree p){ /* 後序遍歷二叉樹*/ if ( p!= NULL ) { PostOrder( p->lchild ) ; PostOrder( p->rchild) ; printf("%c", p->data); } } void Preorder_n(BiTree p){ /*先序遍歷的非遞迴演算法*/ BiTree stack[MAX],q; int top=0,i; for(i=0;i<MAX;i++) stack[i]=NULL;/*初始化棧*/ q=p; while(q!=NULL){ printf("%c",q->data); if(q->rchild!=NULL) stack[top++]=q->rchild; if(q->lchild!=NULL) q=q->lchild; else if(top>0) q=stack[--top]; else q=NULL; } } void release(BiTree t){ /*釋放二叉樹空間*/ if(t!=NULL){ release(t->lchild); release(t->rchild); free(t); } } int main(){ BiTree t=NULL; createBiTree(&t); printf("\n\nPreOrder the tree is:"); PreOrder(t); printf("\n\nInOrder the tree is:"); InOrder(t); printf("\n\nPostOrder the tree is:"); PostOrder(t); printf("\n\n先序遍歷序列(非遞迴):"); Preorder_n(t); release(t); return 0; }
- 執行程式
- 輸入:
ABC##DE#G##F###
- 執行結果:
2.在上題中補充求二叉樹中求結點總數演算法(提示:可在某種遍歷過程中統計遍歷的結點數),並在主函式中補充相應的呼叫驗證正確性。
- 演算法程式碼:
#include<stdio.h>
#include<malloc.h>
#include<iostream>
#include<conio.h>
#define MAX 20
typedef struct BTNode{ /*節點結構宣告*/
char data ; /*節點資料*/
struct BTNode *lchild;
struct BTNode *rchild ; /*指標*/
}*BiTree;
void createBiTree(BiTree *t){ /* 先序遍歷建立二叉樹*/
char s;
BiTree q;
printf("\nplease input data:(exit for #)");
s=getche();
if(s=='#'){*t=NULL; return;}
q=(BiTree)malloc(sizeof(struct BTNode));
if(q==NULL){printf("Memory alloc failure!"); exit(0);}
q->data=s;
*t=q;
createBiTree(&q->lchild); /*遞迴建立左子樹*/
createBiTree(&q->rchild); /*遞迴建立右子樹*/
}
void PreOrder(BiTree p){ /* 先序遍歷二叉樹*/
if ( p!= NULL ) {
printf("%c", p->data);
PreOrder( p->lchild ) ;
PreOrder( p->rchild) ;
}
}
void InOrder(BiTree p){ /* 中序遍歷二叉樹*/
if( p!= NULL ) {
InOrder( p->lchild ) ;
printf("%c", p->data);
InOrder( p->rchild) ;
}
}
void PostOrder(BiTree p){ /* 後序遍歷二叉樹*/
if ( p!= NULL ) {
PostOrder( p->lchild ) ;
PostOrder( p->rchild) ;
printf("%c", p->data);
}
}
void Preorder_n(BiTree p){ /*先序遍歷的非遞迴演算法*/
BiTree stack[MAX],q;
int top=0,i;
for(i=0;i<MAX;i++) stack[i]=NULL;/*初始化棧*/
q=p;
while(q!=NULL){
printf("%c",q->data);
if(q->rchild!=NULL) stack[top++]=q->rchild;
if(q->lchild!=NULL) q=q->lchild;
else
if(top>0) q=stack[--top];
else q=NULL;
}
}
void release(BiTree t){ /*釋放二叉樹空間*/
if(t!=NULL){
release(t->lchild);
release(t->rchild);
free(t);
}
}
int PreOrder_num(BiTree p) {
int j=0;
BiTree stack[MAX],q;
int top=0,i;
for(i=0; i<MAX; i++) stack[i]=NULL; /*初始化棧*/
q=p;
while(q!=NULL) {
j++;
if(q->rchild!=NULL) stack[top++]=q->rchild;
if(q->lchild!=NULL) q=q->lchild;
else
if(top>0) q=stack[--top];
else q=NULL;
}
return j;
}
int main(){
BiTree t=NULL;
createBiTree(&t);
printf("\n\nPreOrder the tree is:");
PreOrder(t);
printf("\n\nInOrder the tree is:");
InOrder(t);
printf("\n\nPostOrder the tree is:");
PostOrder(t);
printf("\n\n先序遍歷序列(非遞迴):");
Preorder_n(t);
printf("\n\n結點總數:");
printf("%d",PreOrder_num(t));
release(t);
return 0;
}
- 執行結果
3.在上題中補充求二叉樹中求葉子結點總數演算法(提示:可在某種遍歷過程中統計遍歷的葉子結點數),並在主函式中補充相應的呼叫驗證正確性。
- 演算法程式碼:
int LeafNodes(BiTree p) {
int num1=0 ,num2=0;
if(p==NULL)
return 0;
else if(p->lchild==NULL&&p->rchild==NULL)
return 1;
else{
num1=LeafNodes(p->lchild) ;
num2=LeafNodes(p->rchild) ;
return (num1+num2);
}
}
int main(){
BiTree t=NULL;
createBiTree(&t);
printf("\n\nPreOrder the tree is:");
PreOrder(t);
printf("\n\nInOrder the tree is:");
InOrder(t);
printf("\n\nPostOrder the tree is:");
PostOrder(t);
printf("\n\n先序遍歷序列(非遞迴):");
Preorder_n(t);
printf("\n\n結點總數:");
printf("%d",PreOrder_num(t));
printf("\n\n葉結點總數:");
printf("%d",LeafNodes(t));
release(t);
return 0;
}
- 執行結果
4.在上題中補充求二叉樹深度演算法,並在主函式中補充相應的呼叫驗證正確性。
- 演算法程式碼:
int BTNodeDepth(BiTree p) {
int lchilddep,rchilddep;
if(p==NULL)
return 0;
else {
lchilddep=BTNodeDepth(p->lchild);
rchilddep=BTNodeDepth(p->rchild);
return(lchilddep>rchilddep)?(lchilddep+1):(rchilddep+1);
}
}
int main(){
BiTree t=NULL;
createBiTree(&t);
printf("\n\nPreOrder the tree is:");
PreOrder(t);
printf("\n\nInOrder the tree is:");
InOrder(t);
printf("\n\nPostOrder the tree is:");
PostOrder(t);
printf("\n\n先序遍歷序列(非遞迴):");
Preorder_n(t);
printf("\n\n結點總數:");
printf("%d",PreOrder_num(t));
printf("\n\n樹的深度:");
printf("%d",BTNodeDepth(t));
release(t);
return 0;
}
- 執行結果
四.實驗小結
- 通過實驗,進一步瞭解二叉樹的先序、中序、後序的遞迴遍歷演算法及非遞迴遍歷演算法,以及求二叉樹的深度、葉子結點數和層序遍歷等演算法。