二叉树的建立及遍历
数据结构实验五
课程数据结构实验名称二叉树的建立及遍历第页
专业班级学号
姓名
实验日期:年月日评分
一、实验目的
1.学会实现二叉树结点结构和对二叉树的基本操作。
2.掌握对二叉树每种操作的具体实现,学会利用递归方法编写对二叉树这种递归数据结构进行处理的算法。
二、实验要求
1.认真阅读和掌握和本实验相关的教材内容。
2.编写完整程序完成下面的实验内容并上机运行。
3.整理并上交实验报告。
三、实验内容
1.编写程序任意输入二叉树的结点个数和结点值,构造一棵二叉树,采用三种递归遍历算法(前序、中序、后序)对这棵二叉树进行遍历并计算出二叉树的高度。
2 .编写程序生成下面所示的二叉树,并采用先序遍历的非递归算法对此二叉
树进行遍历。
四、实验步骤
(描述实验步骤及中间的结果或现象。在实验中做了什么事情,怎么做的,发生的现象和中间结果)
第一题
#include "stdafx.h"
#include"iostream.h"
#include"stdlib.h"
#include"stdio.h"
#include using namespace std; #defineNULL0 #define OK 1 #defineOVERFLOW -1 typedefint Status; typedef struct node { chardata; ?struct node *lchild; struct node*rchild; }*bitree; int k=0; int depth(bitree T)//树的高度 { ?if(!T)return0; else ?{ ?intm=depth(T->lchild); int n=depth(T->rchild); ?return (m>n?m:n)+1; } } //先序,中序建树 structnode*create(char *pre,char *ord,int n) { ?struct node*T; intm; T=NULL; ?if(n<=0) ?{ ?returnNULL; } ?else ?{ ?m=0; ??T=new(struct node); T->data=*pre; ?T->lchild=T->rchild=NULL; ?while(ord[m]!=*pre) ?m++; T->lchild=create(pre+1,ord,m); ?T->rchild=create(pre+m+1,ord+m+1,n-m-1); return T; } } //中序递归遍历 voidinorder(struct node *T) { if(!T) ?return; ?else ?{ ?inorder(T->lchild); cout<<T->data; ??inorder(T->rchild); ?} } void inpre(struct node *T) { ?if(!T) return; else ?{ ??cout< inpre(T->lchild); inpre(T->rchild ); ?? ?} } voidpostorder(struct node *T) { if(!T) ?return; ?else ?{ postorder(T->lchild); ?postorder (T->rchild); ??cout<<T->data; ?} } //先序非递归遍历 voidinpre1(struct node *T) { ?structnode*p; ?structnode *stack[20]; int top=0; p=T; cout<<"非递归先序"; while(p||top!=0) { ??while(p) ??{ ?stack[top++]=p; cout< ??p=p->lchild; ?} ??p=stack[--top]; ? ?p=p->rchild ; } } //中序非递归遍历 void inorder1(struct node *T) { ?struct node*p; ?structnode*stack[20]; ?inttop=0; p=T; ?cout<<"非递归中序"; ?while(p||top!=0) ?{ while(p) ?{ stack[top++]=p;??p=p->lchild ; ?} ?p=stack[--top]; cout< ??p=p->rchild; ?} } //主函数 intmain() { ?bitree T; char pre[30],ord[30]; ?intn,m; gets(pre); ?gets(ord); n=strlen(pre); ?T=create(pre,ord,n); inpre(T); ?cout< ?postorder(T); cout< inorder(T); cout< inpre1(T); ?cout<<endl; inorder1(T); cout<<endl; m=depth(T); cout<<"二叉树高度为:"< ?return 0; } 第二题: #include"stdafx.h" #include"iostream.h" #include"stdlib.h" #include"stdio.h" #include using namespace std; #define NULL 0 #defineOK 1 #defineOVERFLOW-1 typedef intStatus; typedefstruct node { ?char data; ?struct node *lchild; structnode*rchild; }*bitree; Status Create(bitree&T) //按先序次序输入二叉树中结点的值,!表示空树{ chare; cout<<"输入树的元素:"<<endl; cin>>e; if(e=='!') T=NULL; else ?{ if(!(T=(node*)malloc(sizeof(node)))) ?exit(OVERFLOW); ?T->data=e; Create(T->lchild); ??Create(T->rchild); } return OK; } //先序非递归遍历 voidinpre(struct node *T) { struct node*p; ?struct node *stack[20]; inttop=0; ?p=T; cout<<"非递归先序"; while(p||top!=0) ?{ ??while (p) ??{ ??stack[top++]=p; ?cout< data; ???p=p->lchild; ??} ?p=stack[--top]; ? ??p=p->rchild ; ?} } //主函数 intmain() { ?bitree T; Create(T); cout<<"输出的元素为:"< ?inpre(T); return 0; } 五实验结果 第一题: 输入先序为-+a*b%cd/ef 输入后序为a+b*c%d-e/f 得出结果: 输入先序为abcd 输入后序为bacd 得出结果: 第二题: 六实验总结 1 为什么头文件只用#include using namespace std;不行,要把所写到的程序中所包含的头文件头写进去。。于是就在想,反正以后不管这些头文件有没用到头写进去,省得一大堆麻烦。 2 用先序建树的时候虽然只要输入一个字符串,但是要判断空树的情况。比较麻烦。我个人觉得用先序与中序联合建树比较简单。因为这样只要输入先序与中序就可以建树了。 3对于三种遍历的过程,要是用递归写的就根据书上所给出的遍历步骤做稍微的调整就好了。至于非递归的三种遍历,中序最为简单,用一个栈就可以完成了,思路是边进栈边收索左孩子,直到左孩子为空的时候才开始进行出栈输出再收索右孩子的操作。而非递归的先序遍历基本可以和中序一样,建立一个队列,在进栈的时候队列也进同样的元素,但是不与栈一起出栈。而是在最后进栈出栈结束的时候,对队列进行出队列操作即可。 4 二叉树对于进行表达式的前缀,中缀和后缀的表示有明显的优势,既方便,又容易理解。其先序,中序和后序分别对应这表达式的前缀,中缀和后缀。 5在建树与进行树的遍历的时候一定要理解其建树与遍历的整个过程。不然就会连为什么这样做都不知道。在遍历树的时候最常用到的就是栈的结构了(非递归)。 七:思考与提高 1.如何计算二叉链表存储的二叉树中度数为1的结点数? 答:int countleaf(bitree t,int count) { if(!(t->lchild) &&(t->rchild) count++; else if ((t->lchild)&&!(t->rchild)) count++; countleaf(t->lchild); countleaf(t->rchild); return count; } 2.已知有—棵以二叉链表存储的二叉树,root指向根结点,p指向二叉树中任一结点,如何求从根结点到p所指结点之间的路径? 答:void foundp(bitreet) { if(t==p) { Push(s,t->data); Pop(s,t->data); } foundp(t->lchild); foundp(t->rchid); }