1、数据结构二叉树运算器实验报告二叉树运算器一、问题描述本实验主要实现对二叉树的多种方式创建、多种方式遍历、复制、销毁,求二叉树的结点数、叶子数、高度、宽度、每层宽度,用二叉树对中缀式还原,用二叉树进行求值。二、存储结构typedef struct BiTNode TElemType data; struct BiTNode * lchild,* rchild;BiNode,* BiTree;二叉树每个结点包括数据及指向左右孩子的指针。三、算法思想对指针、栈、队列的综合应用。四、程序结构#include#include#include#define STACK_INIT_SIZE 100#defi
2、ne STACKINCREASE 10typedef char TElemType;typedef struct BiTNode TElemType data; struct BiTNode * lchild,* rchild;BiNode,* BiTree;typedef BiTree SElemType;typedef BiTree QElemType;typedef struct QNode QElemType data; struct QNode * next;QNode,*Queue;typedef struct Queue front; Queue rear;LinkQueue;t
3、ypedef struct SElemType *base; SElemType *top; int stacksize;SqStack;/*=栈-ADT=*/void InitStack(SqStack &S) S.base=(SElemType *)malloc(STACK_INIT_SIZE*sizeof(SElemType); S.top=S.base; S.stacksize=STACK_INIT_SIZE;/InitStackvoid Push(SqStack &S,SElemType e) if(S.top-S.base=S.stacksize) S.base=(SElemTyp
4、e *)realloc(S.base,(S.stacksize+STACKINCREASE)*sizeof(SElemType); if(!S.base) exit(1); S.top=S.base+S.stacksize; S.stacksize+=STACKINCREASE; *S.top+=e;int Pop(SqStack &S,SElemType &e) if(S.base=S.top) return -1; e=*-S.top; return 0;/*=队列-ADT=*/void InitQueue(LinkQueue &Q) Q.front=Q.rear=(Queue)mallo
5、c(sizeof(QNode); if(!Q.front) exit(1); Q.front-next=NULL;/InitQueuevoid EnQueue(LinkQueue &Q,QElemType e) Queue p; p=(Queue)malloc(sizeof(QNode); if(!p) exit(1); p-data=e; p-next=NULL; Q.rear-next=p; Q.rear=p; Q.rear-next=NULL;/EnQueueint DeQueue(LinkQueue &Q,QElemType &e) Queue p; if(Q.front=Q.rear
6、) return 0; p=Q.front-next; e=p-data; Q.front-next=p-next; if(Q.rear=p) Q.rear=Q.front; Q.rear-next=NULL; free(p); return 0;/DeQueue/*=二叉树-ADT=*/BiTree PreCreateBiTree() BiTree p; char ch; ch=getchar(); ch=getchar(); if(ch=#) return NULL; p=(BiTree)malloc(sizeof(BiNode); p-data=ch; p-lchild=PreCreat
7、eBiTree(); p-rchild=PreCreateBiTree(); return p;/PreCreateBiTree这是先序扩展序列创建二叉树,主要是递归调用,先赋值给双亲,再进行调用。void PostCreateBiTree1(BiTree &bt) SqStack S; char ch; BiTree p; InitStack(S); while(1) ch=getchar(); ch=getchar(); if(ch=) break; if(ch=#) Push(S,NULL); else p=(BiTree)malloc(sizeof(BiNode); p-data=ch
8、; Pop(S,p-rchild); Pop(S,p-lchild); Push(S,p); Pop(S,bt);/PostCreateBiTree1这是后序扩展序列创建二叉树,序列从左向右输入,以为结束符。扫描入栈时,每当遇到字符,则弹出两个栈顶指针最为右孩子和左孩子,直至遇到结束符。BiTree PostCreateBiTree2() char ch; BiTree p; ch=getchar(); ch=getchar(); if(ch=#) return NULL; p=(BiTree)malloc(sizeof(BiNode); p-data=ch; p-rchild=PostCre
9、ateBiTree2(); p-lchild=PostCreateBiTree2(); return p;/PostCreateBiTree2这也是后序扩展序列创建二叉树,不过是从右向左输入,扫描时,每当遇到#则返回空指针。还是用递归,先创建右孩子,再创建左孩子。int Pre_InCreate(BiTree &bt,char *P,char *Q,int n) int i; bt=(BiTree)malloc(sizeof(BiNode); bt-data=P0; if(n=1) bt-lchild=NULL; bt-rchild=NULL; return 0; for(i=0;ilchil
10、d=(BiTree)malloc(sizeof(BiNode); bt-lchild-data=P1; Pre_InCreate(bt-lchild,P+1,Q,i); else bt-lchild=NULL; if(i!=n-1) bt-rchild=(BiTree)malloc(sizeof(BiNode); bt-rchild-data=P1+i; Pre_InCreate(bt-rchild,P+1+i,Q+1+i,n-1-i); else bt-rchild=NULL; return 0;/Pre_InCreate这是用先序和中序序列创建二叉树。主要通过分析两个序列之间的关系,通过两
11、个序列的头尾指针和结点数,先找到双亲,再找到左右孩子,然后递归调用向下创建。主要注意结点数的变化。int In_PostCreate(BiTree &bt,char *P,char *Q,int n) int i; bt=(BiTree)malloc(sizeof(BiNode); bt-data=Qn-1; if(n=1) bt-lchild=NULL; bt-rchild=NULL; return 0; for(i=0;ilchild=(BiTree)malloc(sizeof(BiNode); bt-lchild-data=Qi-1; In_PostCreate(bt-lchild,P,
12、Q,i); else bt-lchild=NULL; if(i!=n-1) bt-rchild=(BiTree)malloc(sizeof(BiNode); bt-rchild-data=Qn-2; In_PostCreate(bt-rchild,P+i+1,Q+i,n-i-1); else bt-rchild=NULL; return 0;/In_PostCreate这是中序和后序序列创建二叉树。与先序和中序一样,不再多说。不过用先序和后序应该不能创建,因为会产生多种可能。void Visit(TElemType ch) printf(%c,ch);/Visit用来打印data。int Pr
13、eRead(BiTree bt) if(!bt) return 0; Visit(bt-data); PreRead(bt-lchild); PreRead(bt-rchild); return 0;/PreRead先序遍历,先将data打印,再递归调用。int InRead(BiTree bt) if(!bt) return 0; InRead(bt-lchild); Visit(bt-data); InRead(bt-rchild); return 0;/InRead中序遍历,先递归调用左孩子,再打印data,再调用右孩子。int PostRead(BiTree bt) if(!bt) r
14、eturn 0; PostRead(bt-lchild); PostRead(bt-rchild); Visit(bt-data); return 0;/PostRead后序遍历,先将左右孩子递归调用,再打印data。int TierRead(BiTree bt) LinkQueue Q; BiTree p; if(!bt) return 0; InitQueue(Q); EnQueue(Q,bt); while(!(Q.front=Q.rear) DeQueue(Q,p); Visit(p-data); if(p-lchild) EnQueue(Q,p-lchild); if(p-rchil
15、d) EnQueue(Q,p-rchild); return 0;/TierRead按层遍历,运用队列,先将头指针入队,然后首队结点出队打印,每打印一个,其左右孩子入队。直至队列为空。int Number(BiTree bt) int n1,n2; if(!bt) return 0; n1=Number(bt-lchild); n2=Number(bt-rchild); return 1+n1+n2;/Number求二叉树结点数,递归调用,当头指针为空时,返回0,否则返回1+左孩子结点数+右孩子结点数。int Leaf(BiTree bt) int l1,l2; if(!bt) return
16、0; if(!bt-lchild&!bt-rchild) return 1; l1=Leaf(bt-lchild); l2=Leaf(bt-rchild); return l1+l2;/Leaf求二叉树叶子数,递归调用,若头指针为空时,返回0,若头指针左右孩子为空,则返回1,否则返回左孩子叶子数+右孩子叶子数。int Height(BiTree bt) int h1,h2; if(!bt) return 0; h1=Height(bt-lchild); h2=Height(bt-rchild); return 1+(h1h2?h1:h2);/Height求二叉树的高度,递归调用,当头指针为空时
17、,返回0,否则返回1+(左右孩子中高度最大的)。int Wide(BiTree bt,int *w,int x) if(!bt) return 0; if(bt) wx=wx+1; if(bt-lchild) Wide(bt-lchild,w,x+1); if(bt-rchild) Wide(bt-rchild,w,x+1); return 0;/Wide求二叉树的宽度,递归调用,先求得其高度,创建一个数组输入,并输入其层数。若双亲非空wx+。调用其左右孩子。这样就可以得到每层的宽度,找到最大值就是二叉树的宽度。void CopyBiTree(BiTree &P,BiTree Q) BiTre
18、e lp,rp; if(!Q) P=NULL; else CopyBiTree(lp,Q-lchild); CopyBiTree(rp,Q-rchild); P=(BiTree)malloc(sizeof(BiNode); P-data=Q-data; P-lchild=lp; P-rchild=rp; /CopyBiTree复制二叉树,仍是递归调用。从下向上、从左到右创建,当头指针为空时,赋值空指针。int DestroyBiTree(BiTree &bt) if(!bt) return 0; if(bt-lchild) DestroyBiTree(bt-lchild); if(bt-rch
19、ild) DestroyBiTree(bt-rchild); if(!bt-lchild&!bt-rchild) free(bt); bt=NULL; return 0; return 0;/DestroyBiTree销毁二叉树,递归调用。如果头指针为空,返回。调用左右孩子,如果左右孩子为空,释放双亲。开始先判断左右孩子是否非空,程序很长。经过调整,最后判断,使函数大大缩减了。int Calculate(BiTree bt) int l,r; if(!bt-lchild&!bt-rchild) return bt-data-48; l=Calculate(bt-lchild); r=Calcu
20、late(bt-rchild); switch(bt-data) case +: return l+r; case -: return l-r; case *: return l*r; case /: return l/r; return 0;/Calculate计算二叉树的值,递归调用。如果左右孩子为空,返回其ASCII码-48,即其实数值。开始不是在返回时减去48,而是在计算时减去,不好操作,最后改在返回时减去48。计算左孩子值和右孩子值,根据算数符号返回相应的值。int Restore(BiTree bt) if(!bt) return 0; if(bt-data=*|bt-data=/
21、)&(bt-lchild-data=+|bt-lchild-data=-) printf(); Restore(bt-lchild); printf(); else Restore(bt-lchild); Visit(bt-data); if(bt-data=*|bt-data=/)&(bt-rchild-data=+|bt-rchild-data=-) printf(); Restore(bt-rchild); printf(); else Restore(bt-rchild); return 0;/Restore还原二叉树,利用中序遍历。如果双亲是*或者/,左孩子是+或-,则在打印左孩子两
22、边加上()。否则直接打印。中间打印双亲。右孩子同理。/*=main=*/void main() int n,m,i,j,x,y; char *p; char *q; int *w; BiTree S10; for(i=0;i9|i0) printf(位置选择错误!请重新选择存储位置(0-9):); scanf(%d,&i); else if(Si) printf(已占用!请重新选择存储位置:); scanf(%d,&i); else break; switch(n) case 1: printf( (1)请输入扩展先序序列:); Si=PreCreateBiTree(); break; cas
23、e 2: printf( (2)请输入扩展后序序列(从左到右输入):); PostCreateBiTree1(Si); break; case 3: printf( (3)请输入扩展后序序列(从右到左输入):); Si=PostCreateBiTree2(); break; case 4: printf( (4)请输入结点数:); scanf(%d,&x); p=(char *)malloc(x*sizeof(char); if(!p) exit(1); q=(char *)malloc(x*sizeof(char); if(!q) exit(1); printf( (4)请输入先序序列:);
24、 for(j=0;jx;j+) pj=getchar(); pj=getchar(); printf( (4)请输入中序序列:); for(j=0;jx;j+) qj=getchar(); qj=getchar(); Pre_InCreate(Si,p,q,x); break; case 5: printf( (5)请输入结点数:); scanf(%d,&x); p=(char *)malloc(x*sizeof(char); if(!p) exit(1); q=(char *)malloc(x*sizeof(char); if(!q) exit(1); printf( (5)请输入中序序列:
25、); for(j=0;jx;j+) pj=getchar(); pj=getchar(); printf( (5)请输入后序序列:); for(j=0;jx;j+) qj=getchar(); qj=getchar(); In_PostCreate(Si,p,q,x); free(p); free(q); break; printf(1.创建完成.n); break; case 2: printf(2.遍历方式:n (1)t先序遍历n (2)t中序遍历n (3)t后序遍历n (4)t按层遍历n (5)t全部显示n 请选择(); scanf(%d,&n); printf( (%d)请选择遍历位置:,n); scanf(%d,&i); if(!Si) printf(NULLn); break; switch(n) case 1: pr
copyright@ 2008-2022 冰豆网网站版权所有
经营许可证编号:鄂ICP备2022015515号-1