实验三树图.docx
《实验三树图.docx》由会员分享,可在线阅读,更多相关《实验三树图.docx(40页珍藏版)》请在冰豆网上搜索。
实验三树图
中国矿业大学计算机学院实验报告
课程名称:
数据结构实验名称:
树、图的实现应用
一、实验目的
1理解树结构的逻辑特性
2熟练掌握二叉树的逻辑结构特性及各种存储方法
3熟练掌握二插树的各种基本操作,尤其是三种遍历
4熟练掌握图的存储结构
5掌握图的邻接矩阵和邻接表表示分别进行深度和广度优先搜索遍历的算法。
6了解图的最小生成树算法。
二、实验内容与代码
基本题
1、给定一棵用链表表示的二叉树,其根指针为root,试写出求二叉树结点数目。
程序代码:
//db.cpp:
Definestheentrypointfortheconsoleapplication.
//
#include"stdafx.h"
#include
usingnamespacestd;
typedefstructNode
{
charchElem;
Node*lchild,*rchild;
}BTNode,*BTREE;
//创建二叉树;
voidBuildBT(BTREE&root)
{
charchA='';
cin>>chA;
if(chA=='')
{
root=NULL;
}
//递归创建二叉树;
else
{
root=(BTREE)malloc(sizeof(BTNode));
root->chElem=chA;
BuildBT(root->lchild);
BuildBT(root->rchild);
}
}
//求解二叉树中结点的个数
intNodeNumber(BTREE&root)
{
intiSum=0;
BTREEQueue[100],p;//创建队列;
intiFront=0,iRear=0;
Queue[1]=root;
iFront=iRear=1;
while(iFront<=iRear)
{
p=Queue[iFront];
iFront++;//元素出队;
iSum++;
if(p->lchild)
{
iRear++;
Queue[iRear]=p->lchild;
}//使其入队;
if(p->rchild)
{
iRear++;
Queue[iRear]=p->rchild;
}//入队操作;
}
returniSum;
}
//求二叉树中结点的个数;
intcount(BTREE&T)
{
//intnum=0;
if(T){
return1+count(T->lchild)+count(T->rchild);
}elsereturn0;
}
intmain(intargc,char*argv[])
{
BTREEroot;
cout<<"树的结点元素为单个字符,请输入一个字符:
"<BuildBT(root);
cout<<"您的二叉树的结点数目为:
"<cout<return0;
}
实验结果截图:
2、对图的邻接矩阵和邻接表表示分别进行深度优先搜索遍历算法的实现。
程序代码:
//图的基本操作
#include"stdafx.h"
#include
#defineMaxValueINT_MAX//定义最大值即(无穷大)
#defineMaxVNum100//定义最大顶点个数
usingnamespacestd;
//建立邻接矩阵的结构
voidADJMATRIX(intA[][MaxVNum],intn,inte)
{
intiWeight=0;//定义权值;
for(inti=0;ifor(intj=0;j{
A[i][j]=MaxValue;
}
inti=0,j=0;
for(intk=0;k{
cin>>i>>j>>iWeight;
A[i][j]=iWeight;
A[j][i]=A[i][j];
}
}
//图的临接表结构表示方法
//边结点的数据类型
typedefstructEdge
{
intadjvex;//边的终止顶点在顶点结点中的位置;
intweight;//该边的权值;
Edge*next;//指向下一个边结点
}Elink;
//顶点结点的类型;
typedefstructVer
{
intvertex;//顶点中存储的数据信息为整形数据;
Elink*link;//指向第1条边所对应的边结点;
}VLink;
//依次输入带权有向图的n个结点,和e个表示边的顶点偶对,建立其邻接表结构
voidADJLIST(VLinkG[],intn,inte)
{
intvi,vj;
Elink*p,*q;
for(intk=0;k{
G[k].vertex=k+1;
G[k].link=NULL;
}//建立n个顶点结点;
inti=0,j=0,weight=0;
for(intk=0;k{
cin>>i>>j>>weight;
p=(Elink*)malloc(sizeof(Elink));//申请建立一个边结点;
p->adjvex=vj-1;
p->weight=weight;
p->next=NULL;
if(!
G[vi-1].link)
{
G[vi-1].link=p;//若第vi个链表只有头结点;
}
else
{
q=G[vi-1].link;
while(q->next)
q=q->next;//找到第vi个链表的表尾结点;
q->next=p;//将新结点插入到第vi个链表表尾;
}
}
}
//删除图中数据信息为item的那个顶点
voidDelVer(VLinkG[],intn,intitem)
{
intk=-1;
Elink*p,*q,*r;
for(inti=0;i{
if(G[i].vertex==item)
{
k=i;//记录满足条件的顶点;
break;
}
if(k!
=-1)
{
p=G[k].link;
for(inti=k+1;i{
G[i-1].vertex=G[i].vertex;
G[i-1].link=G[i].link;
}
}
n--;//图中的顶点数目减1;
while(p!
=NULL)
{
r=p;
p=p->next;
free(r);
}//删除并释放第k个链表的所有边结点;
for(inti=0;i{
p=G[i].link;
while(p!
=NULL)
{
if(p->adjvex==k)
{
if(G[i].link==p)
{
G[i].link=p->next;//删除p所指的边结点;
}
else
{
q->next=p->next;
}
r=p;
p=p->next;
free(r);
}
else
{
if(p->adjvex>k)
{
p->adjvex--;//p所指边结点的adjvex域减1;
}
q=p;
p=p->next;//p向后移动到下一个边结点;
}
}
}
}
}
//visit函数的定义
voidVisit(intm)
{
cout<}
intvisited[];
//深度优先遍历搜索;
voidDFS(VLinkG[],intv)
{
Visit(v);//访问顶点v;
visited[v]=1;//将顶点v对应的访问标记位置为1;
intw=FIRSTADJ(G,v);//求v的第1个邻接点,若无邻接点,则返回-1;
while(w!
=-1)
{
if(visited[w]==0)
{
DFS(G,w);
}
w=NEXTADJ(G,v);//求下一个邻接点,若无邻接点,则返回为-1;
}
}
//对图进行深度优先搜索的主算法;
voidTRAVEL_DFS(VLinkG[],intvisited[],intn)
{
for(inti=0;i{
visited[i]=0;//标记数组赋初值;
}
for(inti=0;i{
if(visited[i]==0)
{
DFS(G,i);
}
}
}
//广度优先搜索的算法;
voidBFS(VLinkG[],intv)
{
Visit(v);
visited[v]=1;//顶点v对应的访问标记置为1;
ADDQ(Q,v);
intw=0;
while(!
EMPTYQ(Q))
{
v=DELQ(Q);//退出队头元素送v;
w=FIRSTADJ(G,v);//求v的第1个邻接点,无邻接点,返回-1;
while(w!
=-1)
{
if(visited[w]==0)
{
Visit(w);//访问顶点w;
ADDQ(Q,w);//当前被访问的顶点w进队;
visited[w]=1;//顶点w对应的访问标记置为1;
}
w=NEXTADJ(G,v);//求v的下一个邻接点,无邻接点返回-1;
}
}
}
//广度优先搜索的主算法如下;
voidTRAVEL_BFS(VLinkG[],intvisited[],intn)
{
for(inti=0;i{
visited[i]=0;//标记数组赋初值(清零);
}
for(inti=0;i{
if(visited[i]==0)
{
BFS(G,i);
}
}
}
intmain(intargc,char*argv[])
{
intiArr[5][MaxVNum];
intiNum=5;
intiTem=5;
ADJMATRIX(iArr,iNum,iTem);
return0;
}
加强题
1、试写出中序遍历二叉树的递归和非递归程序并调试。
程序代码:
/*1、试写出中序遍历二叉树的递归和非递归程序并调试。
*/
#include"stdafx.h"
#include
usingnamespacestd;
typedefstructNode
{
charchElem;
Node*lchild,*rchild;
}BTNode,*BTREE;
//创建一个二叉树;
voidBuildBT(BTREE&root)
{
charchA='';
cin>>chA;
if(chA=='')
{
root=NULL;
}
else
{
root=(BTREE)malloc(sizeof(BTNode));
root->chElem=chA;
BuildBT(root->lchild);//遍历创建左孩子;
BuildBT(root->rchild);//遍历创建右孩子;
}
}
//输出各个结点的值;
voidPrint(BTREE&root)
{
cout<chElem<<"";
cout<}
//递归法实现中序遍历;
voidMidOrder(BTREE&root)
{
if(root)
{
MidOrder(root->lchild);//遍历左子树;
Print(root);
MidOrder(root->rchild);//遍历右子树;
}
}
//非递归法实现中序遍历;
voidMidOrder1(BTREE&root)
{
BTREEStack[50],p=root;
intiTop=-1;
if(root)
{
do
{
while(p)
{
Stack[++iTop]=p;
p=p->lchild;//将p移到左孩子结点上;
}
p=Stack[iTop--];//退栈;
Print(p);
p=p->rchild;//将p移到右孩子结点上;
}while(!
(p==NULL&&iTop==-1));
}
}
intmain(intargc,char*argv[])
{
BTREEroot;
cout<<"树的结点元素为单个字符,请输入一个字符:
"<BuildBT(root);
MidOrder(root);
//MidOrder1(root);
return0;
}
结果运行图
2、写出中序线索二叉树的中序遍历程序并调试。
程序代码:
/*2、写出中序线索二叉树的中序遍历程序并调试。
*/
#include"stdafx.h"
#include
usingnamespacestd;
//线索二叉树的建立;
typedefstructNode
{
charchElem;//存放数据域;
Node*lchild,*rchild;//指向左右子树;
intlbit,rbit;//左右标志域;
}TBTNode,*TBTREE;
//建立线索二叉树;
voidBuildTBT(TBTREE&root)
{
charchA='';
cin>>chA;
if(chA=='')
{
root=NULL;
}
else
{
root=(TBTREE)malloc(sizeof(TBTNode));
root->chElem=chA;
BuildTBT(root->lchild);//遍历创建左孩子结点;
BuildTBT(root->rchild);//遍历创建右孩子结点;
}
}
//在中序二叉树中确定x指结点的直接后继结点;
TBTREEInsucc(TBTREEx)
{
TBTREEs;
s=x->rchild;
if(x->rbit==1)
{
while(s->lbit==1)
{
s=s->lchild;
}
}
returns;
}
//打印结点的元素;
voidPrint(TBTREE&root)
{
cout<chElem<<"";
cout<}
//利用中序线索二叉树进行中序遍历程序;
voidMidTOrder(TBTREE&root)
{
TBTREEp=root;
while
(1)
{
p=Insucc(p);//求p所指的直接后继结点;
if(p==root)
{
break;
}
Print(p);//打印p所指的结点;
}
}
intmain(intargc,char*argv[])
{
TBTREEroot;
BuildTBT(root);
MidTOrder(root);
return0;
}
提高题
1、实现霍夫曼编、解码
(1)输入一系列字符及其出现频率并以此构造霍夫曼树进行编码并输出码表,另输入一段文字,对其进行霍夫曼编码。
例:
CASTCASTSATATATASA
(2)在1中已构成的霍夫曼树的基础上,输入一段01编码,要求输出其解码的原文。
例:
111011*********011001001001001100
程序代码:
#include"stdafx.h"
#include
#include
#include
#definen8
#definem2*n-1
#definemax2000
typedefstruct
{
intwi;
chardata;
intParent,Lchild,Rchild;
}huffm;
huffmHT[m+1];
typedefstruct
{
charbits[n+1];
intstart;
charch;
}ctype;
voidHuffmTree(huffmHT[m+1]);
voidHuffmcode(ctypecode[n+1]);
voidOutput(ctypecode[n+1]);
/*构1造¨¬HuffmTree的Ì?
函¡¥数ºy*/
voidHuffmTree(huffm*HT)
{
inti,j,p1,p2;
ints1,s2;
//for(i=1;i<=n;i++)
//{
//scanf("%d",&w);
//HT[i].wi=w;
//}
for(i=n+1;i<=m;i++)
{
p1=p2=0;
s1=s2=max;
for(j=1;j<=i-1;j++)
if(HT[j].Parent==0)
if(HT[j].wi{
s2=s1;
s1=HT[j].wi;
p2=p1;p1=j;
}
elseif(HT[j].wi{
s2=HT[j].wi;
p2=j;
}
HT[p1].Parent=HT[p2].Parent=i;
HT[i].Lchild=p1;
HT[i].Rchild=p2;
HT[i].wi=HT[p1].wi+HT[p2].wi;
}
//printf("\nOK!
");
//for(i=1;i<=m;i++)
//{
//printf("\n");
//printf("%d",HT[i].wi);
//}
//getchar();
return;
}
/*求¨®HuffmTree编À¨¤码?
的Ì?
函¡¥数ºy*/
voidHuffmcode(ctypecode[n+1])
{
inti,p,s;
ctypemd;
for(i=1;i<=n;i++)
{
md.ch=code[i].ch;
md.start=n+1;
s=i;
p=HT[i].Parent;
while(p!
=0)
{
md.start--;
if(HT[p].Lchild==s)
md.bits[md.start]='0';
else
md.bits[md.start]='1';
s=p;
p=HT[p].Parent;
}
code[i]=md;
}
}
/*打䨰印®?
编À¨¤码?
函¡¥数ºy*/
voidOutput(ctypecode[n+1])
{
inti,j;
for(i=1;i<=n;i++)
{
printf("\n");
printf("%c",code[i].ch);
for(j=1;j<=8;j++)
{
if(jprintf("");
else
if((code[i].bits[j]=='0')||(code[i].bits[j]=='1'))
printf("%c",code[i].bits[j]);
}
printf("%d",code[i].start);
}
}
voidmain()
{
inti,j;
intw;
intflag=1;
intchoice;
ctypecode[n+1];
chartemp[n+1];
inttemp2[n+1];
printf("Wouldyouw