二叉樹的操作
內容:
(1)採用下列方法之一建立二叉樹的二叉鏈表:
① 輸入完全二叉樹的先序序列,用#代表虛結點(空指針),如ABD###CE##F##,建立二叉樹的二叉鏈表。
② 已知二叉樹的先序遍歷序列和中序遍歷序列,或者已知二叉樹的中序遍歷序列和後序遍歷序列,建立二叉樹的二叉鏈表。
③ 將一棵二叉樹的所有結點存儲在一維數組中,虛結點用#表示,利用二叉樹的性質5,建立二叉樹的二叉鏈表。例如用數組a存儲的二叉樹的結點如下(0單元不用):
(2)寫出對用二叉鏈表存儲的二叉樹進行先序、中序和後序遍歷的遞歸和非遞歸算法。
(3)寫出對用二叉鏈表存儲的二叉樹進行層次遍歷算法。
(4)求二叉樹的所有葉子及結點總數。
(5)求二叉樹的深度。
要求:
(1)熟練掌握二叉樹的書序存儲結構和二叉鏈表的存儲結構。
(2)掌握二叉樹常用的四種遍歷方法:先序遍歷、中序遍歷、後序遍歷和層次遍歷。
(3)會利用二叉樹的遍歷思想,實現對二叉樹的各種操作。
`#include<stdio.h>
#include<stdlib.h>
#define stackinitsize 100
#define stackincrement 10
#define max 100
//二叉樹的類型定義
typedef struct bitnode{
char data;
struct bitnode *lchild,*rchild;
}bitnode,*bitree;
//棧的類型定義
typedef struct {
bitree *base;
int top;
int stacksize;
}sqstack;
//隊列的類型定義
typedef struct{
bitree *base;
int front,rear;
}cqqueue;
void initstack(sqstack &S){
//初始化棧
S.base=(bitree*)malloc(stackinitsize*sizeof(bitree));
if(!S.base)
return ;
S.top=0;
S.stacksize=stackinitsize;
}
int stackempty(sqstack S){
//判空
if(S.top==0)
return 1;
return 0;
}
void push(sqstack &S,bitree e){
//入棧
S.base[S.top++]= e;
}
void pop(sqstack &S,bitree &e){
//出棧
if(S.top==0){
return ;
}
e=S.base[--S.top];
}
bitree gettop(sqstack &S,bitree &e){
e=S.base[S.top-1];
return S.base[S.top-1];
}
void initqueue(cqqueue &Q){
//建隊列
Q.base=(bitree*)malloc(max*sizeof(bitree));
if(!Q.base)
return;
Q.front=Q.rear=0;
}
int Queueempty(cqqueue Q){
//判空
if(Q.rear==Q.front)
return 1;
return 0;
}
void enqueue(cqqueue &Q,bitree e){
//入隊列
if((Q.rear+1)%max==Q.front)
return;
Q.base[Q.rear]=e;
Q.rear=(Q.rear+1)%max;
}
void dequeue(cqqueue &Q,bitree &e){
//出隊列
if(Q.rear==Q.front)
return;
e=Q.base[Q.front];
Q.front=(Q.front+1)%max;
}
void creatbitree(bitree &bt){
//建立二叉鏈表
char ch;
ch=getchar();
if(ch=='#')
bt=NULL;
else{
if(!(bt=(bitnode*)malloc(sizeof(bitnode))))
return;
bt->data=ch;
creatbitree(bt->lchild);
creatbitree(bt->rchild);
}
}
void visit(char b){
//輸出
printf("%c ",b);
}
void preordertraversexianxu(bitree bt){
//遞歸遍歷算法--先序
if(bt){
visit(bt->data);
preordertraversexianxu(bt->lchild);
preordertraversexianxu(bt->rchild);
}
}
void preordertraversezhongxu(bitree bt){
//遞歸遍歷算法——中序
if(bt){
preordertraversezhongxu(bt->lchild);
visit(bt->data);
preordertraversezhongxu(bt->rchild);
}
}
void preordertraversehouxu(bitree bt){
//遞歸遍歷算法——後序
if(bt){
preordertraversehouxu(bt->lchild);
preordertraversehouxu(bt->rchild);
visit(bt->data);
}
}
void traversexianxu(bitree bt){
//先序遍歷
bitree p;
if(bt){
sqstack S;
initstack(S);
push(S,bt);
while(!stackempty(S)){
while(gettop(S,p) && p){
visit(p->data);
push(S,p->lchild);
}
pop(S,p);
if(!stackempty(S)){
pop(S,p);
push(S,p->rchild);
}
}
}
}
void traversezhongxu(bitree bt){
//中序遍歷
if(bt){
sqstack S;
initstack(S);
bitree p;
push(S,bt);
while(!stackempty(S)){
while(gettop(S,p) && p){
push(S,p->lchild);
}
pop(S,p);
if(!stackempty(S)){
pop(S,p);
visit(p->data);
push(S,p->rchild);
}
}
}
}
void traversehouxu(bitree bt){
//後序遍歷
if(bt){
sqstack S;
bitree p;
bitree q;
initstack(S);
push(S,bt);
while(!stackempty(S)){
while(gettop(S,p) && p)
push(S,p->lchild);
pop(S,p);
if(!stackempty(S)){
gettop(S,p);
if(p->rchild)
push(S,p->rchild);
else{
pop(S,p);
visit(p->data);
while(!stackempty(S) && gettop(S,q) && q->rchild==p){
pop(S,p);
visit(p->data);
}
if(!stackempty(S)){
gettop(S,p);
push(S,p->rchild);
}
}
}
}
}
}
void levetraverse(bitree bt){
//二叉鏈表存儲的層次遍歷
if(bt){
bitree p;
cqqueue Q;
initqueue(Q);
enqueue(Q,bt);
while(!Queueempty(Q)){
dequeue(Q,p);
visit(p->data);
if(p->lchild) enqueue(Q,p->lchild);
if(p->rchild) enqueue(Q,p->rchild);
}
}
}
void countleaf(bitree bt,int &leaves){
//求葉子節點總數
if(bt){
countleaf(bt->lchild,leaves);
if(!bt->lchild && !bt->rchild)
leaves++;
countleaf(bt->rchild,leaves);
}
}
int Count(bitree bt)
{
//求二叉樹的節點總數
if(bt==NULL)
return 0; //空二叉樹結點數爲0
else //左右子樹結點總數加1
return Count(bt->lchild)+Count(bt->rchild)+1;
}
int bitreedepth(bitree bt){
//bt的深度
int depthl,depthr;
if(bt==NULL)//與if(bt)有何區別??
return 0;
else{
depthl=bitreedepth(bt->lchild);
depthr=bitreedepth(bt->rchild);
if(depthl>=depthr)
return depthl+1;
else
return depthr+1;
}
}
int main()
{
int leaf=0,depth;
bitree bt; //爲什麼要用*bt??
creatbitree(bt);
printf("遞歸遍歷的結果-先序:");
preordertraversexianxu(bt);//遞歸遍歷
printf("\n遞歸遍歷的結果-中序:");
preordertraversezhongxu(bt);//遞歸遍歷
printf("\n遞歸遍歷的結果-後序:");
preordertraversehouxu(bt);//遞歸遍歷
printf("\n非遞歸先序遍歷結果:");
traversexianxu(bt);//先序遍歷
printf("\n非遞歸中序遍歷結果:");
traversezhongxu(bt);//中序遍歷
printf("\n非遞歸後序遍歷結果:");
traversehouxu(bt);//後序遍歷
printf("\n層次遍歷結果:");
levetraverse(bt);//層次遍歷
countleaf(bt,leaf);//葉子節點總數
printf("\n葉子節點總數 %d\n",leaf);
printf("二叉樹的節點總數:%d\n",Count(bt));
depth=bitreedepth(bt);//bt的深度
printf("二叉樹的深度 %d\n",depth);
}`