树和二叉树一 数据结构实验.docx
《树和二叉树一 数据结构实验.docx》由会员分享,可在线阅读,更多相关《树和二叉树一 数据结构实验.docx(22页珍藏版)》请在冰豆网上搜索。
![树和二叉树一 数据结构实验.docx](https://file1.bdocx.com/fileroot1/2023-6/2/a783b02c-46b1-492a-a63e-3b7a834fd251/a783b02c-46b1-492a-a63e-3b7a834fd2511.gif)
树和二叉树一数据结构实验
实验报告
May14
2015
姓名:
陈斌学号:
E11314079专业:
13计算机科学与技术
数据结构第三次实验
学号E11314079专业计算机科学与技术姓名陈斌
实验日期2015.05.14教师签字成绩
实验报告
【实验名称】树和二叉树
(一)
【实验目的】
1.掌握二叉树的二叉链表存储表示;
2.掌握二叉树的遍历算法;
3.运用遍历算法求解有关问题。
【实验内容】
1.必做内容
任务1:
以算法6.4创建二叉树的存储结构,树的具体形态自定。
任务2:
对任务1中的二叉树分别实现先序、中序、后序遍历(递归实现)和中序遍历的非递归实现以及层序遍历;
任务3:
统计1中树的结点总数、叶子结点总数以及树的高度;
源代码:
head.h:
#include
#include
#include//malloc()
#include//INT,MAX
#include//EOF,NULL
#include//atoi()
#include//eof()
#include//floor(),ceil(),abs()
#include//exit()
#include//cout,cin
//函数结果状态代码
#defineTRUE1
#defineFALSE0
#defineOK1
#defineERROR0
#defineINFEASIBLE-1
//OVERFLOW在math.h中已定义为3
typedefintStatus;
typedefintBoolean;//布尔类型
head2.h:
#defineSTACK_INIT_SIZE100
#defineSTACKINCREMENT10
typedefstruct{
SElemType*base;
SElemType*top;
intstacksize;
}SqStack;
typedefstructQNode
{
QElemTypedata;
structQNode*next;
}QNode,*QueuePtr;
typedefstruct
{
QueuePtrfront,rear;/*队头、队尾指针*/
}LinkQueue;
StatusInitStack(SqStack&S)
{/*构造一个空栈S*/
S.base=(SElemType*)malloc(STACK_INIT_SIZE*sizeof(SElemType));
if(!
S.base)
exit(OVERFLOW);/*存储分配失败*/
S.top=S.base;
S.stacksize=STACK_INIT_SIZE;
returnOK;
}
StatusStackEmpty(SqStack&S)
{/*若栈S为空栈,则返回TRUE,否则返回FALSE*/
if(S.top==S.base)
returnTRUE;
else
returnFALSE;
}
StatusGetTop(SqStack&S,QElemType&e)
{/*若栈不空,则用e返回S的栈顶元素,并返回OK;否则返回ERROR*/
if(S.top>S.base)
{
e=*(S.top-1);
returnOK;
}
else
returnERROR;
}
StatusPush(SqStack&S,QElemType&e)
{/*插入元素e为新的栈顶元素*/
if(S.top-S.base>=S.stacksize)/*栈满,追加存储空间*/
{
S.base=(SElemType*)realloc(S.base,(S.stacksize+STACKINCREMENT)*sizeof(SElemType));
if(!
S.base)
exit(OVERFLOW);/*存储分配失败*/
S.top=S.base+S.stacksize;
S.stacksize+=STACKINCREMENT;
}
*S.top++=e;
returnOK;
}
StatusPop(SqStack&S,QElemType&e)
{/*若栈不空,则删除S的栈顶元素,用e返回其值,并返回OK;否则返回ERROR*/
if(S.top==S.base)
returnERROR;
e=*--S.top;
returnOK;
}
StatusInitQueue(LinkQueue&Q)
{/*构造一个空队列Q*/
Q.front=Q.rear=(QueuePtr)malloc(sizeof(QNode));
if(!
Q.front)
exit(OVERFLOW);
Q.front->next=NULL;
returnOK;
}
StatusQueueEmpty(LinkQueue&Q)
{/*若Q为空队列,则返回TRUE,否则返回FALSE*/
if(Q.front==Q.rear)
returnTRUE;
else
returnFALSE;
}
StatusEnQueue(LinkQueue&Q,QElemTypee)
{/*插入元素e为Q的新的队尾元素*/
QueuePtrp=(QueuePtr)malloc(sizeof(QNode));
if(!
p)/*存储分配失败*/
exit(OVERFLOW);
p->data=e;
p->next=NULL;
Q.rear->next=p;
Q.rear=p;
returnOK;
}
StatusDeQueue(LinkQueue&Q,QElemType&e)
{/*若队列不空,删除Q的队头元素,用e返回其值,并返回OK,否则返回ERROR*/
QueuePtrp;
if(Q.front==Q.rear)
returnERROR;
p=Q.front->next;
e=p->data;
Q.front->next=p->next;
if(Q.rear==p)
Q.rear=Q.front;
free(p);
returnOK;
}
main.cpp:
typedefcharTElemType;
#include"head.h"
typedefstructBiTNode{
TElemTypedata;
structBiTNode*lchild,*rchild;
}BiTNode,*BiTree;
typedefBiTreeQElemType;/*设队列元素为二叉树的指针类型*/
typedefBiTreeSElemType;/*设栈元素为二叉树的指针类型*/
#include"head2.h"
StatusInitBiTree(BiTree&T)
{/*操作结果:
构造空二叉树T*/
T=NULL;
returnOK;
}
StatusCreateBiTree(BiTree&T)
{//算法6.4:
按先序次序输入二叉树中结点的值(字符型),构造二叉链表表示的二叉树T。
TElemTypech;
scanf("%c",&ch);
if(ch=='')/*空*/
T=NULL;
else
{
T=(BiTree)malloc(sizeof(BiTNode));
if(!
T)
exit(OVERFLOW);
T->data=ch;/*生成根结点*/
CreateBiTree(T->lchild);/*构造左子树*/
CreateBiTree(T->rchild);/*构造右子树*/
}
returnOK;
}
StatusPreOrderTraverse(BiTreeT,Status(*Visit)(TElemType))
{/*初始条件:
二叉树T存在,Visit是对结点操作的应用函数。
算法6.1*/
/*操作结果:
先序递归遍历T,对每个结点调用函数Visit一次且仅一次*/
if(T)/*T不空*/
{
if(Visit(T->data))/*先访问根结点*/
if(PreOrderTraverse(T->lchild,Visit))/*再先序遍历左子树*/
if(PreOrderTraverse(T->rchild,Visit))/*最后先序遍历右子树*/
returnOK;
returnERROR;
}
else
returnOK;
}
StatusInOrderTraverse(BiTreeT,Status(*Visit)(TElemType))
{/*初始条件:
二叉树T存在,Visit是对结点操作的应用函数*/
/*操作结果:
中序递归遍历T,对每个结点调用函数Visit一次且仅一次*/
if(T)
{
if(InOrderTraverse(T->lchild,Visit))/*先中序遍历左子树*/
if(Visit(T->data))/*再访问根结点*/
if(InOrderTraverse(T->rchild,Visit))/*最后中序遍历右子树*/
returnOK;
returnERROR;
}
else
returnOK;
}
StatusPostOrderTraverse(BiTreeT,Status(*Visit)(TElemType))
{/*初始条件:
二叉树T存在,Visit是对结点操作的应用函数*/
/*操作结果:
后序递归遍历T,对每个结点调用函数Visit一次且仅一次*/
if(T)/*T不空*/
{
if(PostOrderTraverse(T->lchild,Visit))/*先后序遍历左子树*/
if(PostOrderTraverse(T->rchild,Visit))/*再后序遍历右子树*/
if(Visit(T->data))/*最后访问根结点*/
returnOK;
returnERROR;
}
else
returnOK;
}
StatusInOrderTraverse1(BiTreeT,Status(*Visit)(TElemType))
{/*采用二叉链表存储结构,Visit是对数据元素操作的应用函数。
*/
/*中序遍历二叉树T的非递归算法(利用栈),对每个数据元素调用函数Visit*/
SqStackS;
InitStack(S);
while(T||!
StackEmpty(S))
{
if(T)
{/*根指针进栈,遍历左子树*/
Push(S,T);
T=T->lchild;
}
else
{/*根指针退栈,访问根结点,遍历右子树*/
Pop(S,T);
if(!
Visit(T->data))
returnERROR;
T=T->rchild;
}
}
printf("\n");
returnOK;
}
StatusInOrderTraverse2(BiTreeT,Status(*Visit)(TElemType))
{/*采用二叉链表存储结构,Visit是对数据元素操作的应用函数。
算法6.2*/
/*中序遍历二叉树T的非递归算法(利用栈),对每个数据元素调用函数Visit*/
SqStackS;
BiTreep;
InitStack(S);
Push(S,T);/*根指针进栈*/
while(!
StackEmpty(S))
{
while(GetTop(S,p)&&p)
Push(S,p->lchild);/*向左走到尽头*/
Pop(S,p);/*空指针退栈*/
if(!
StackEmpty(S))
{/*访问结点,向右一步*/
Pop(S,p);
if(!
Visit(p->data))
returnERROR;
Push(S,p->rchild);
}
}
printf("\n");
returnOK;
}
voidLevelOrderTraverse(BiTreeT,Status(*Visit)(TElemType))
{/*初始条件:
二叉树T存在,Visit是对结点操作的应用函数*/
/*操作结果:
层序递归遍历T(利用队列),对每个结点调用函数Visit一次且仅一次*/
LinkQueueq;
QElemTypea;
if(T)
{
InitQueue(q);
EnQueue(q,T);
while(!
QueueEmpty(q))
{
DeQueue(q,a);
Visit(a->data);
if(a->lchild!
=NULL)
EnQueue(q,a->lchild);
if(a->rchild!
=NULL)
EnQueue(q,a->rchild);
}
printf("\n");
}
}
StatusvisitT(TElemTypee)
{
printf("%c",e);
returnOK;
}
StatusBiTreeNodeNum(BiTreeT)//结点总个数
{
if(T)
returnBiTreeNodeNum(T->lchild)+BiTreeNodeNum(T->rchild)+1;
else
return0;
}
StatusBiTreeLeafNodeNum(BiTreeT)//叶子结点个数
{
if(T)
{
if(!
T->lchild&&!
T->rchild)
return1;
else
returnBiTreeLeafNodeNum(T->lchild)+BiTreeLeafNodeNum(T->rchild);
}
elsereturn0;
}
StatusBiTreeDepth(BiTreeT)//树的深度
{
if(!
T)
return0;
else
return(BiTreeDepth(T->lchild)>BiTreeDepth(T->rchild)?
BiTreeDepth(T->lchild):
BiTreeDepth(T->rchild))+1;
}
voidmain()
{
BiTreeT;
InitBiTree(T);
cout<<"请先序输入二叉树(如:
ab三个空格表示a为根结点,b为左子树的二叉树):
"<CreateBiTree(T);
cout<<"先序遍历序列:
"<PreOrderTraverse(T,visitT);
cout<cout<<"中序遍历序列:
"<InOrderTraverse(T,visitT);
cout<cout<<"后序遍历序列:
"<PostOrderTraverse(T,visitT);
cout<cout<<"中序遍历的非递归实现1(利用栈):
"<InOrderTraverse1(T,visitT);
cout<<"中序遍历的非递归实现2(利用栈):
"<InOrderTraverse2(T,visitT);
cout<<"层序遍历(利用队列):
"<LevelOrderTraverse(T,visitT);
cout<<"树的结点总数为:
"<cout<<"树的叶子结点总数为:
"<cout<<"树的深度为:
"<}
运行结果:
树的形状:
先序输入:
ABGCDEHF(“”代表空格)
2.选做内容
任务4:
修改算法6.4(结点及二叉树类型分别用BiThrNode,BiThrTree,创建根结点的语句也要进行修改),然后对所创建的二叉树进行中序线索化;
任务5:
对任务4得到的中序线索化树进行中序遍历。
源代码:
head.h:
#include
#include
#include//malloc()
#include//INT,MAX
#include//EOF,NULL
#include//atoi()
#include//eof()
#include//floor(),ceil(),abs()
#include//exit()
#include//cout,cin
//函数结果状态代码
#defineTRUE1
#defineFALSE0
#defineOK1
#defineERROR0
#defineINFEASIBLE-1
//OVERFLOW在math.h中已定义为3
typedefintStatus;
typedefintBoolean;//布尔类型
head2.h:
typedefcharTElemType;
typedefenum{Link,Thread}PointerTag;/*Link(0):
指针,Thread
(1):
线索*/
typedefstructBiThrNode
{
TElemTypedata;
structBiThrNode*lchild,*rchild;/*左右孩子指针*/
PointerTagLTag,RTag;/*左右标志*/
}BiThrNode,*BiThrTree;
main.cpp:
#include"head.h"
#include"head2.h"
StatusCreateBiThrTree(BiThrTree&T)
{/*按先序输入二叉线索树中结点的值,构造二叉线索树T*/
/*空格表示空结点*/
TElemTypeh;
scanf("%c",&h);
if(h=='')
T=NULL;
else
{
T=(BiThrTree)malloc(sizeof(BiThrNode));
if(!
T)
exit(OVERFLOW);
T->data=h;/*生成根结点(先序)*/
CreateBiThrTree(T->lchild);/*递归构造左子树*/
if(T->lchild)/*有左孩子*/
T->LTag=Link;
CreateBiThrTree(T->rchild);/*递归构造右子树*/
if(T->rchild)/*有右孩子*/
T->RTag=Link;
}
returnOK;
}
BiThrTreepre;
voidInThreading(BiThrTreep)
{/*中序遍历进行中序线索化。
算法6.7*/
if(p)
{
InThreading(p->lchild);/*递归左子树线索化*/
if(!
p->lchild)/*没有左孩子*/
{
p->LTag=Thread;/*前驱线索*/
p->lchild=pre;/*左孩子指针指向前驱*/
}
if(!
pre->rchild)/*前驱没有右孩子*/
{
pre->RTag=Thread;/*后继线索*/
pre->rchild=p;/*前驱右孩子指针指向后继(当前结点p)*/
}
pre=p;/*保持pre指向p的前驱*/
InThreading(p->rchild);/*递归右子树线索化*/
}
}
StatusInOrderThreading(BiThrTree&Thrt,BiThrTreeT)
{/*中序遍历二叉树T,并将其中序线索化,Thrt指向头结点。
算法6.6*/
Thrt=(BiThrTree)malloc(sizeof(BiThrNode));
if(!
Thrt)
exit(OVERFLOW);
Thrt->LTag=Link;/*建头结点*/
Thrt->RTag=Thread;
Thrt->rchild=Thrt;/*右指针回指*/
if(!
T)/*若二叉树空,则左指针回指*/
Thrt->lchild=Thrt;
else
{
Thrt->lchild=T;
pre=Thrt;
InThreading(T);/*中序遍历进行中序线索化*/
pre->rchild=Thrt;
pre->RTag=Thread;/*最后一个结点线索化*/
Thrt->rchild=pre;
}
returnOK;
}
StatusInOrderTraverse_Thr(BiThrTreeT,Status(*Visit)(TElemType))
{/*中序遍历二叉线索树T(头结点)的非递归算法。
算法6.5*/
BiThrTreep;
p=T->lchild;/*p指向根结点*/
while(p!
=T)
{/*空树或遍历结束时,p==T*/
while(p->LTag==Link)
p=p->lchild;
if(!
Visit(p->data))/*访问其左子树为空的结点*/
returnERROR;
while(p->RTag==Thread&&p->rchild!
=T)
{
p=p->rchild;
Visit(p->data);/*访问后继结点*/