北理工数据结构实验三
- 格式:docx
- 大小:57.31 KB
- 文档页数:12
北理工数据结构实验三
《数据结构与算法设计》
实验报告
——实验三
学院:
班级:
学号:
姓名:
一、实验目的
1.通过实验实践、巩固二叉树和队列的相关操作;
2.熟悉VC环境,加强编程、调试的练习;
3.用C语言实现二叉树和队列的抽象数据类型;
4.用C语言编写递归函数,实现生成二叉树和遍历二叉树;
5.用队列实现二叉树的层次遍历;
6.理论知识与实际问题相结合,利用上述基本操作用多种方式遍历二叉树。
二、实验内容
1、遍历二叉树。
请输入一棵二叉树的扩展的前序序列,经过处理后生成一棵二叉树,然后对于该二叉树输出前序、中序和后序遍历序列。
2、选做:按层次遍历二叉树。
三、程序设计
1、概要设计
为实现上述程序功能,需要建立抽象数据类型:二叉树和队列。
(1)、定义抽象数据类型
二叉树的抽象数据类型定义为:
ADT BinaryTree {
数据对象D:D是具有相同特性的数据元素的集合。
数据关系R: 若D=Φ,则R=Φ,称BinaryTree为空二叉树;
若D≠Φ,则R={H},H是如下二元关系;
(1)在D中存在惟一的称为根的数据元素root,它在关系H下无前驱;
(2)若D-{root}≠Φ,则存在D-{root}={D1,Dr},且D1∩Dr =Φ;
(3)若D1≠Φ,则D1中存在惟一的元素x1,∈H,且存在D1上的关系
H1 ?H;若Dr≠Φ,则Dr中存在惟一的元素xr,∈H,且存在上的关系
Hr ?H;H={,,H1,Hr};
(4)(D1,{H1})是一棵符合本定义的二叉树,称为根的左子树;(Dr,{Hr})是一棵
符合本定义的二叉树,称为根的右子树。
基本操作:
CreatBiTree(BiTree &T)
操作结果:按先序次序建立二叉链表表示的二叉树T
PreOrderTraverse(BiTree T)
初始条件:二叉树T已经存在
操作结果:先序遍历二叉树T ,对每个结点输出其数据元素
InOrderTraverse(BiTree T)
初始条件:二叉树T已经存在
操作结果:中序遍历二叉树T ,对每个结点输出其数据元素
PostOrderTraverse(BiTree T)
初始条件:二叉树T已经存在
操作结果:后序遍历二叉树T ,对每个结点输出其数据元素
LevelOrderTraverse(BiTree T)
初始条件:二叉树T已经存在
操作结果:层次遍历二叉树T ,对每个结点输出其数据元素} ADT
BinaryTree
队列的抽象数据类型定义为: ADT Stack{
数据对象:D={ai|ai∈ElemSet,i=1,2,3……,n,n≥0}
数据关系:R1={ |ai∈D,i=1,2,……,n}
约定其中a1端为队列头,an端为队列尾
基本操作:
InitQueue(&Q)
功能:构造一个空队列Q。
EnQueue(&Q, e )
功能:将元素e插入Q的队尾。
DeQueue(&Q,&e)
功能:删除Q的队头元素。
}ADT Stack
⑵主程序流程
主程序先调用CreatBiTree(BiTree &T)函数,根据输入的先序序列构造出一棵二叉树,再依次调用PreOrderTraverse(BiTree T),InOrderTraverse(BiTree T),PostOrderTraverse(BiTree T),LevelOrderTraverse(BiTree T)函数对该二叉树进行先序、中序、后序、层次遍历并输出结果。
⑶模块调用关系
由主函数调用生成二叉树模块,调用先序、中序、后序遍历模块依次输出,调用层次遍历模块,调用队列的建立、插入、删除等模块,完成层次遍历并输出。
⑷流程图 2、详细设计
(1)、宏定义
#define MAXSIZE 100 //最大队列长度
#define OK 1 //操作无误
#define ERROR 0 //操作有误
#define OVERFLOW -2 //溢出
(2)、抽象数据类型定义
typedef int Status; //函数类型
typedef char ElemType; //二叉树的元素类型
typedef struct BiTNode
{//定义二叉树 ElemType data; struct BiTNode * lchild, * rchild; //左孩子和右孩子的指针}BiTNode, * BiTree;
typedef BiTree QElemType; //队列的元素类型
typedef struct
{//定义队列
QElemType * base; //初始化时分配存储空间的基址
int front; //队头指针,指向队头元素
int rear; //队尾指针,指向队尾元素的下一个位置
}SqQueue;
(3)、操作算法程序实现:
Status InitQueue(SqQueue &Q )
{//构造一个空队列Q
Q.base=(QElemType * )
malloc (MAXSIZE * sizeof (QElemType));
if ( !Q.base ) exit (OVERFLOW); //存储分配失败
Q.front = Q.rear = 0;
return OK;
}//InitQueue
Status EnQueue( SqQueue &Q, QElemType e )
{//将元素e插入队尾
if ( (Q.rear+1)%MAXSIZE==Q.front )
return ERROR ; //队满
Q.base[Q.rear] = e ; //将元素e插入队尾Q.rear =
(Q.rear+1)%MAXSIZE; //修改队尾指针
return OK;
}//EnQueue
Status DeQueue( SqQueue &Q, QElemType &e )
{ //删除队头元素,用e返回其值,并返回OK;否则返回ERROR
if ( Q.rear==Q.front )
return ERROR ; //队空 e = Q.base[Q.front] ; // 取队头元素 e Q.front =
(Q.front+1)%MAXSIZE; //修改队头指针
return OK;
}//EnQueue
int CreateBiTree(BiTree &T)
{//按先序次序建立二叉链表表示的二叉树T
ElemType ch;
scanf ("%c",&ch);
if ( ch ==' ') T=NULL; // 若ch==' ' 则表示空子树
else {
if ( ! (T=( BiTNode * ) malloc( sizeof( BiTNode ) ) ) )
exit(OVERFLOW);
T->data = ch; // 建立(根)结点
CreateBiTree(T->lchild); // 递归构造左子树链表
CreateBiTree(T->rchild); // 递归构造右子树链表
}
return OK;
}//CreateBiTree
void PreOrderTraverse( BiTree T)
{//先序遍历以T为根结点指针的二叉树
if (T) //若二叉树不为空
{ printf("%c",T->data); //访问根结点
PreOrderTraverse(T->lchild); //先序遍历T的左子树
PreOrderTraverse(T->rchild); //先序遍历T的右子树
}
} //PreOrderTraverse
void InOrderTraverse( BiTree T)
{//中序遍历以T为根结点指针的二叉树
if (T) //若二叉树不为空
{ InOrderTraverse(T->lchild); //中序遍历T的左子树 printf("%c",T->data); //访问根结点
InOrderTraverse(T->rchild); //中序遍历T的右子树
}
} //InOrderTraverse
void PostOrderTraverse( BiTree T)
{//后序遍历以T为根结点指针的二叉树
if (T) //若二叉树不为空
{ PostOrderTraverse(T->lchild); //后序遍历T的左子树
PostOrderTraverse(T->rchild); //后序遍历T的右子树
printf("%c",T->data); //访问根结点
}
} //PostOrderTraverse
void LevelOrderTraverse(BiTree T)
{//层次遍历以T为根结点指针的二叉树
SqQueue q;
BiTree p;
InitQueue(q);
if(T) EnQueue(q,T); //队头元素进队列
while(!(q.front==q.rear)){
DeQueue(q,p);
printf("%c",p->data); //输出队头元素
if(p->lchild) EnQueue(q,p->lchild); //左子树进队列
if(p->rchild) EnQueue(q,p->rchild); //右子树进队列
}
}
四、程序调试分析
1.程序中用到的未定义的字符串要进行宏定义;
2.输入二叉树时要注意用空格代替子树为空;
3.二叉树的层次遍历可以借助队列来实现;
4.先定义二叉树,再定义队列元素的数据结构为二叉树类型,顺