数据结构实验报告.docx
《数据结构实验报告.docx》由会员分享,可在线阅读,更多相关《数据结构实验报告.docx(37页珍藏版)》请在冰豆网上搜索。
![数据结构实验报告.docx](https://file1.bdocx.com/fileroot1/2022-11/24/45089d72-52c2-4dc0-abbd-a23b9fdca08f/45089d72-52c2-4dc0-abbd-a23b9fdca08f1.gif)
数据结构实验报告
甘肃政法学院
本科生实验报告
(三)
姓名:
学院:
专业:
班级:
实验课程名称:
数据结构
实验日期:
2013年05月24日
指导教师及职称:
实验成绩:
开课时间:
2012~2013学年第二学期
实验题目
数据结构实验
小组合作
姓名
班级
学号
一、实验目的
7.1.实现二叉树的各种基本运算的算法
7.2.实现二叉树的各种遍历算法
7.3.求二叉树中从根节点到叶子节点的路径
7.4.由遍历序列构造二叉树
7.5.实现中序线索化二叉树
7.6.构造哈夫曼树
7.7.用二叉树来表示代数表达式
二.实验环境
计算机、VisualC++
三、实验内容与步骤
7.1.编写一个程序algo7-1.cpp,实现二叉树的各种运算,并在此基础上设计一个程序exp7-1.cpp完成如下功能(b为如图7.1所示的一棵二叉树):
1.输出二叉树b;
2.输出H节点的左、右孩子节点值;
3.输出二叉树b的深度;
4.输出二叉树b的宽度;
5.输出二叉树b的节点个数;
6.输出二叉树b的叶子节点个数;
7.释放二叉树b;
主程序如下:
#include
typedefcharElemType;
typedefstructnode
{
ElemTypedata;//数据元素
structnode*lchild;//指向左孩子
structnode*rchild;//指向右孩子
}BTNode;
externvoidCreateBTNode(BTNode*&b,char*str);
externBTNode*FindNode(BTNode*b,ElemTypex);
externBTNode*LchildNode(BTNode*p);
externBTNode*RchildNode(BTNode*p);
externintBTNodeDepth(BTNode*b);
externvoidDispBTNode(BTNode*b);
externintBTWidth(BTNode*b);
externintNodes(BTNode*b);
externintLeafNodes(BTNode*b);
externvoidDestroyBTNode(BTNode*&b);
voidmain()
{
BTNode*b,*p,*lp,*rp;;
CreateBTNode(b,"A(B(D,E(H(J,K(L,M(,N))))),C(F,G(,I)))");
printf("二叉树的基本运算如下:
\n");
printf("
(1)输出二叉树:
");DispBTNode(b);printf("\n");
printf("
(2)H节点:
");
p=FindNode(b,'H');
if(p!
=NULL)
{
lp=LchildNode(p);
if(lp!
=NULL)
printf("左孩子为%c",lp->data);
else
printf("无左孩子");
rp=RchildNode(p);
if(rp!
=NULL)
printf("右孩子为%c",rp->data);
else
printf("无右孩子");
}
printf("\n");
printf("(3)二叉树b的深度:
%d\n",BTNodeDepth(b));
printf("(4)二叉树b的宽度:
%d\n",BTWidth(b));
printf("(5)二叉树b的节点个数:
%d\n",Nodes(b));
printf("(6)二叉树b的叶子节点个数:
%d\n",LeafNodes(b));
printf("(7)释放二叉树b\n");
DestroyBTNode(b);
}
运行结果如下:
7.2.设计一个程序exp7-2.cpp,实现二叉树的先序遍历、中序遍历和后序遍历的各种递归和非递归算法,以及层次遍历的算法。
并对图7.1所示的二叉树b给出求解结果。
主程序如下:
#include
#include
#defineMaxSize100
typedefcharElemType;
typedefstructnode
{
ElemTypedata;//数据元素
structnode*lchild;//指向左孩子
structnode*rchild;//指向右孩子
}BTNode;
externvoidCreateBTNode(BTNode*&b,char*str);
externvoidDispBTNode(BTNode*b);
externvoidDestroyBTNode(BTNode*&b);
voidPreOrder(BTNode*b)//先序遍历的递归算法
{
if(b!
=NULL)
{
printf("%c",b->data);//访问根节点
PreOrder(b->lchild);//递归访问左子树
PreOrder(b->rchild);//递归访问右子树
}
}
voidPreOrder1(BTNode*b)
{
BTNode*St[MaxSize],*p;
inttop=-1;
if(b!
=NULL)
{
top++;//根节点入栈
St[top]=b;
while(top>-1)//栈不为空时循环
{
p=St[top];//退栈并访问该节点
top--;
printf("%c",p->data);
if(p->rchild!
=NULL)//右孩子入栈
{
top++;
St[top]=p->rchild;
}
if(p->lchild!
=NULL)//左孩子入栈
{
top++;
St[top]=p->lchild;
}
}
printf("\n");
}
}
voidInOrder(BTNode*b)//中序遍历的递归算法
{
if(b!
=NULL)
{
InOrder(b->lchild);//递归访问左子树
printf("%c",b->data);//访问根节点
InOrder(b->rchild);//递归访问右子树
}
}
voidInOrder1(BTNode*b)
{
BTNode*St[MaxSize],*p;
inttop=-1;
if(b!
=NULL)
{
p=b;
while(top>-1||p!
=NULL)
{
while(p!
=NULL)
{
top++;
St[top]=p;
p=p->lchild;
}
if(top>-1)
{
p=St[top];
top--;
printf("%c",p->data);
p=p->rchild;
}
}
printf("\n");
}
}
voidPostOrder(BTNode*b)//后序遍历的递归算法
{
if(b!
=NULL)
{
PostOrder(b->lchild);//递归访问左子树
PostOrder(b->rchild);//递归访问右子树
printf("%c",b->data);//访问根节点
}
}
voidPostOrder1(BTNode*b)
{
BTNode*St[MaxSize];
BTNode*p;
intflag,top=-1;//栈指针置初值
if(b!
=NULL)
{
do
{
while(b!
=NULL)//将t的所有左节点入栈
{
top++;
St[top]=b;
b=b->lchild;
}
p=NULL;//p指向当前节点的前一个已访问的节点
flag=1;
while(top!
=-1&&flag)
{
b=St[top];//取出当前的栈顶元素
if(b->rchild==p)//右子树不存在或已被访问,访问之
{
printf("%c",b->data);//访问*b节点
top--;
p=b;//p指向则被访问的节点
}
else
{
b=b->rchild;//t指向右子树
flag=0;
}
}
}while(top!
=-1);
printf("\n");
}
}
voidTravLevel(BTNode*b)
{
BTNode*Qu[MaxSize];//定义循环队列
intfront,rear;//定义队首和队尾指针
front=rear=0;//置队列为空队列
if(b!
=NULL)
printf("%c",b->data);
rear++;//节点指针进入队列
Qu[rear]=b;
while(rear!
=front)//队列不为空
{
front=(front+1)%MaxSize;
b=Qu[front];//队头出队列
if(b->lchild!
=NULL)//输出左孩子,并入队列
{
printf("%c",b->lchild->data);
rear=(rear+1)%MaxSize;
Qu[rear]=b->lchild;
}
if(b->rchild!
=NULL)//输出右孩子,并入队列
{
printf("%c",b->rchild->data);
rear=(rear+1)%MaxSize;
Qu[rear]=b->rchild;
}
}
printf("\n");
}
voidmain()
{
BTNode*b;
CreateBTNode(b,"A(B(D,E(H(J,K(L,M(,N))))),C(F,G(,I)))");
printf("二叉树b:
");DispBTNode(b);printf("\n");
printf("层次遍历序列:
");
TravLevel(b);
printf("先序遍历序列:
\n");
printf("递归算法:
");PreOrder(b);printf("\n");
printf("非递归算法:
");PreOrder1(b);
printf("中序遍历序列:
\n");
printf("递归算法:
");InOrder(b);printf("\n");
printf("非递归算法:
");InOrder1(b);
printf("后序遍历序列:
\n");
printf("递归算法:
");PostOrder(b);printf("\n");
printf("非递归算法:
");PostOrder1(b);
DestroyBTNode(b);
}
运行结果如下:
7.3.对如图7.1所示的二叉树,设计一个程序exp7-3.cpp完成如下功能:
1.输出所有的叶子节点
2.输出所有从叶子节点到根节点的路径
3.输出2中的第一条最长的路径
主程序如下:
#include
#include
#defineMaxSize100
typedefcharElemType;
typedefstructnode
{
ElemTypedata;//数据元素
structnode*lchild;//指向左孩子
structnode*rchild;//指向右孩子
}BTNode;
externvoidCreateBTNode(BTNode*&b,char*str);//在algo7-1.cpp文件中
externvoidDispBTNode(BTNode*b);
externvoidDestroyBTNode(BTNode*&b);
voidAllPath(BTNode*b)
{
structsnode
{
BTNode*node;//存放当前节点指针
intparent;//存放双亲节点在队列中的位置
}
Qu[MaxSize];//定义顺序队列
intfront,rear,p;//定义队头和队尾指针
front=rear=-1;//置队列为空队列
rear++;
Qu[rear].node=b;//根节点指针进入队列
Qu[rear].parent=-1;//根节点没有双亲节点
while(front{
front++;
b=Qu[front].node//队头出队列
if(b->lchild==NULL&&b->rchild==NULL)//*b为叶子节点
{
printf("%c到根节点逆路径:
",b->data);
p=front;
while(Qu[p].parent!
=-1)
{
printf("%c",Qu[p].node->data);
p=Qu[p].parent;
}
printf("%c\n",Qu[p].node->data);
}
if(b->lchild!
=NULL)//左孩子入队列
{
rear++;
Qu[rear].node=b->lchild;
Qu[rear].parent=front;
}
if(b->rchild!
=NULL)//右孩子入队列
{
rear++;
Qu[rear].node=b->rchild;
Qu[rear].parent=front;
}
}
}
voidAllPath1(BTNode*b,ElemTypepath[],intpathlen)
{
inti;
if(b!
=NULL)
{
if(b->lchild==NULL&&b->rchild==NULL)//*b为叶子节点
{
printf("%c到根节点逆路径:
%c",b->data,b->data);
for(i=pathlen-1;i>=0;i--)
printf("%c",path[i]);
printf("\n");
}
else
{
path[pathlen]=b->data;//将当前节点放入路径中
pathlen++;//路径长度增
AllPath1(b->lchild,path,pathlen);//递归扫描左子树
AllPath1(b->rchild,path,pathlen);//递归扫描右子树
pathlen--;//恢复环境
}
}
}
voidLongPath(BTNode*b,ElemTypepath[],intpathlen,ElemTypelongpath[],int&longpathlen)
{
inti;
if(b==NULL)
{
if(pathlen>longpathlen)//若当前路径更长,将路径保存在longpath中
{
for(i=pathlen-1;i>=0;i--)
longpath[i]=path[i];
longpathlen=pathlen;
}
}
else
{
path[pathlen]=b->data;//将当前节点放入路径中
pathlen++;//路径长度增
LongPath(b->lchild,path,pathlen,longpath,longpathlen);//递归扫描左子树
LongPath(b->rchild,path,pathlen,longpath,longpathlen);//递归扫描右子树
pathlen--;//恢复环境
}
}
voidDispLeaf(BTNode*b)
{
if(b!
=NULL)
{if(b->lchild==NULL&&b->rchild==NULL)
printf("%c",b->data);
else
{
DispLeaf(b->lchild);
DispLeaf(b->rchild);
}
}
}
voidmain()
{
BTNode*b;
ElemTypepath[MaxSize],longpath[MaxSize];
inti,longpathlen=0;
CreateBTNode(b,"A(B(D,E(H(J,K(L,M(,N))))),C(F,G(,I)))");
printf("二叉树b:
");DispBTNode(b);printf("\n");
printf("b的叶子节点:
");DispLeaf(b);printf("\n");
printf("AllPath:
\n");AllPath(b);
printf("AllPath1:
\n");AllPath1(b,path,0);
LongPath(b,path,0,longpath,longpathlen);
printf("第一条最长逆路径长度:
%d\n",longpathlen);
printf("第一条最长逆路径:
");
for(i=longpathlen-1;i>=0;i--)
printf("%c",longpath[i]);
printf("\n");
DestroyBTNode(b);
}运行结果如下:
7.4.设计一个程序exp7-4.cpp,实现由先序遍历序列和中序遍历序列以及由中序遍历序列和后序遍历序列构造一棵二叉树的功能,要求以括号表示和凹入表示法输出该二叉树。
并用先序遍历序列“ABDEHJKLMNCFGI”和中序遍历序列“DBJHLKMNEAFCGI”以及由中序遍历序列“DBJHLKMNEAFCGI”和后序遍历序列“DJLNMKHEBFIGCA”进行验证。
主程序如下:
#include
#include
#defineMaxSize100
#defineMaxWidth40
typedefcharElemType;
typedefstructnode
{
ElemTypedata;//数据元素
structnode*lchild;//指向左孩子
structnode*rchild;//指向右孩子
}BTNode;
externvoidDispBTNode(BTNode*b);
externvoidDestroyBTNode(BTNode*&b);
BTNode*CreateBT1(char*pre,char*in,intn)
{
BTNode*s;
char*p;
intk;
if(n<=0)returnNULL;
s=(BTNode*)malloc(sizeof(BTNode));//创建二叉树节点*s
s->data=*pre;
for(p=in;pif(*p==*pre)
break;
k=p-in;
s->lchild=CreateBT1(pre+1,in,k);
s->rchild=CreateBT1(pre+k+1,p+1,n-k-1);
returns;
}
BTNode*CreateBT2(char*post,char*in,intn,intm)
{
BTNode*s;
char*p,*q,*maxp;
intmaxpost,maxin,k;
if(n<=0)returnNULL;
maxpost=-1;
for(p=in;pfor(q=post;qif(*p==*q)
{
k=q-post;
if(k>maxpost)
{
maxpost=k;
maxp=p;
maxin=p-in;
}
}
s=(BTNode*)malloc(sizeof(BTNode));//创建二叉树节点*s
s->data=post[maxpost];
s->lchild=CreateBT2(post,in,maxin,m);
s->rchild=CreateBT2(post,maxp+1,n-maxin-1,m);
returns;
}
voidDispBTNode1(BTNode*b)//以凹入表表示法输出一棵二叉树
{
BTNode*St[MaxSize],*p;
intlevel[MaxSize][2],top=-1,n,i,width=4;
chartype;
if(b!
=NULL)
{
top++;
St[top]=b;//根节点入栈
level[top][0]=width;
level[top][1]=2;//2表示是根
while(top>-1)
{
p=St[top];//退栈并凹入显示该节点值
n=level[top][0];
switch(level[top][1])
{
case0:
type='L';break;//左节点之后输出(L)
case1:
type='R';break;//右节点之后输出(R)
case2:
type='B';break;//根节点之后前输出(B)
}
for(i=1;i<=n;i++)//其中n为显示场宽,字符以右对齐显示
printf("");
printf("%c(%c)",p->data,type);
for(i=n+1;i<=MaxWidth;i+=2)
printf("--");
printf("\n");
top--;
if(p->rchild!
=NULL)
{//将右子树根节点入栈
top++;
St[top]=p->rchild;
level[top][0]=n+width;//显示场宽增width
level[top][1]=1;//1表示是右子树
}
if(p->lchild!
=NULL)
{//将左子树根节点入栈
top++;
St[top]=p->lchild;
level[top][0]=n+width;//显示场宽增width
level[top][1]=0;//0表示是左子树
}
}
}
}
voidmain()
{
BTNode*b;
ElemTypepre[]="ABDEHJKLMNCFGI";
ElemTypein[]="DBJHLKMNEAFCGI";
ElemTypepost[]="DJLNMKHEBFIGCA";
b=CreateBT1(pre,in,14);
printf("先序序列:
%s\n",pre);
printf("中序序列:
%s\n",in);
printf("构造一棵二叉树b:
\n");
printf("括号表示法:
");DispBTNode(b);printf("\n");
p