数据结构课程设计报告模板图的遍历.docx
《数据结构课程设计报告模板图的遍历.docx》由会员分享,可在线阅读,更多相关《数据结构课程设计报告模板图的遍历.docx(19页珍藏版)》请在冰豆网上搜索。
![数据结构课程设计报告模板图的遍历.docx](https://file1.bdocx.com/fileroot1/2023-1/3/fd94ff28-7736-40b7-9db5-7beb5048c435/fd94ff28-7736-40b7-9db5-7beb5048c4351.gif)
数据结构课程设计报告模板图的遍历
数据结构
课程设计报告书
设计题目图遍历的演示
姓名
专业班级
学号
指导教师
成绩
评语
2014年6月20日
目录
目录1
一、功能需求1
(一)原始数据1
(二)系统功能1
三、程序总体设计2
(一)数据结构2
(二)函数原形清单2
(三)程序总体框架4
(四)详细代码4
四、程序清单15
五、总结17
一、功能需求
以邻接多重表为存储结构,实现连通无向图的深度优先和广度优先遍历。
以用户指定的顶点为起点,分别输出每种遍历下的顶点访问序列和相应生成树的边集。
二、系统功能和原始数据
(一)原始数据
设图的顶点不超过20个,每个顶点用一个编号表示(如果一个图有n个顶点,则它们的编号分别为1,2,…,n)。
通过输入图的全部边输入一个图,每条边为一对整数,可以对边的输入顺序作某种限制。
注意,生成树的边是有向边,端点顺序不能颠倒。
(二)系统功能
1.创建无向图
2.打印无向图
3.深度优先搜索
4.广度优先搜索
三、程序总体设计
(一)数据结构
typedefstructEBox
{
intmark;//访问标记,1代表已访问,0代表未访问
intivex,jvex;//该边依附的两个顶点的位置
structEBox*ilink,*jlink;//分别指向依附这两个顶点的下一条边
//InfoType*info;//该边信息指针
}EBox;
typedefstructVexBox
{
VertexTypedata;
EBox*firstedge;//指向第一条依附该顶点的边
}VexBox;
typedefstruct
{
VexBoxadjmulist[NUM];
intvexnum,edgenum;//无向图的当前顶点数和边数
}AMLGraph;
//---------------------------------------------------队列的定义
typedefintQElemType;
typedefstructQNode
{
QElemTypedata;
structQNode*next;
}QNode,*QueuePtr;
typedefstruct
{
QueuePtrfront,rear;
}LinkQueue;
(二)函数原形清单
intLocateVex(AMLGraphG,VertexTypeu)
//寻找输入的数据在图中的位置,若不存在则返回-1
intCreateGraph(AMLGraph&G)
//采用邻接多重表存储表示,构造无向图G
VertexType*GetVex(AMLGraphG,intv)//返回V的值
intFirstAdjVex(AMLGraphG,VertexTypev)//返回V的第一个邻接点的序号,若没有则返回-1
intNextAdjVex(AMLGraphG,VertexTypev,VertexTypew)//返回V的(相对于W)的下一个邻接结点的序号,若W是V的最后一个邻接结点,则返回-1
voidDFS(AMLGraphG,intv)//深度优先搜索//深度优先遍历图
voidDFSTraverse(AMLGraphG,int(*Visit)(VertexType))
intInitQueue(LinkQueue*Q)//队列的初始化
intQueueEmpty(LinkQueueQ)//判断队列是否为空,为空则返回1,否则返回0
intEnQueue(LinkQueue*Q,QElemTypee)//向队列中插入元素
intDeQueue(LinkQueue*Q,QElemType*e)//若队列不为空,则删除对头元素,并返回1;否则返回0
voidBFSTraverse(AMLGraphG,int(*Visit)(VertexType))//广度优先非递归遍历图G
voidMarkUnVisited(AMLGraphG)//把边的访问标记设置为0,即未被访问
voidDisplay(AMLGraphG)//显示构造的无向图(包括定点数、顶点、边数、边)
(三)程序总体框架
(四)详细代码
#include
usingnamespacestd;
//--------------------------------------------------------无向图的邻接多重表存储结构的定义
constintNUM=20;
constintData_Num=2;//每个顶点所表示的数据
typedefcharVertexType[Data_Num];
typedefstructEBox
{
intmark;//访问标记,1代表已访问,0代表未访问
intivex,jvex;//该边依附的两个顶点的位置
structEBox*ilink,*jlink;//分别指向依附这两个顶点的下一条边
}EBox;
typedefstructVexBox
{
VertexTypedata;
EBox*firstedge;//指向第一条依附该顶点的边
}VexBox;
typedefstruct
{
VexBoxadjmulist[NUM];
intvexnum,edgenum;//无向图的当前顶点数和边数
}AMLGraph;
//---------------------------------------------------队列的定义
typedefintQElemType;
typedefstructQNode
{
QElemTypedata;
structQNode*next;
}QNode,*QueuePtr;
typedefstruct
{
QueuePtrfront,rear;
}LinkQueue;
//寻找输入的数据在图中的位置,若不存在则返回-1
intLocateVex(AMLGraphG,VertexTypeu)
{
inti;
for(i=0;iif(strcmp(u,G.adjmulist[i].data)==0)
returni;
return-1;
}
//采用邻接多重表存储表示,构造无向图G
intCreateGraph(AMLGraph&G)
{
cout<<"请输入图的顶点数、边数:
";
cin>>G.vexnum;//输入图当前的顶点数
cin>>G.edgenum;//输入图当前的边数
cout<<"请输入每个顶点所对应的值:
"<for(inti=0;i{
cin>>G.adjmulist[i].data;//输入顶点值
G.adjmulist[i].firstedge=NULL;//初始化指针
}
VertexTypev1,v2;
EBox*p;
intj;//每条弧所关联的两个结点
for(intk=0;k{
cout<<"请输入第"<";
cin>>v1;cin>>v2;
i=LocateVex(G,v1);j=LocateVex(G,v2);//确定v1和v2在图G中的位置
p=(EBox*)malloc(sizeof(EBox));
//对弧结点进行赋值
(*p).mark=0;
(*p).ivex=i;
(*p).jvex=j;
(*p).ilink=G.adjmulist[i].firstedge;
(*p).jlink=G.adjmulist[j].firstedge;
G.adjmulist[i].firstedge=G.adjmulist[j].firstedge=p;
}
return1;
}
//返回V的值
VertexType*GetVex(AMLGraphG,intv)
{
if(v>G.vexnum||v<0)
exit(0);
return&G.adjmulist[v].data;
}
//返回V的第一个邻接点的序号,若没有则返回-1
intFirstAdjVex(AMLGraphG,VertexTypev)
{
inti;
i=LocateVex(G,v);
if(i<0)
return-1;
if(G.adjmulist[i].firstedge)//V有邻接结点
if(G.adjmulist[i].firstedge->ivex==i)
returnG.adjmulist[i].firstedge->jvex;
else
returnG.adjmulist[i].firstedge->ivex;
else
return-1;
}
//返回V的(相对于W)的下一个邻接结点的序号,若W是V的最后一个邻接结点,则返回-1
intNextAdjVex(AMLGraphG,VertexTypev,VertexTypew)
{
inti,j;
EBox*p;
i=LocateVex(G,v);
j=LocateVex(G,w);
if(i<0||j<0)
return-1;
p=G.adjmulist[i].firstedge;
while(p)
if(p->ivex==i&&p->jvex!
=j)
p=p->ilink;
elseif(p->jvex==i&&p->ivex!
=j)
p=p->jlink;
else
break;
if(p&&p->ivex==i&&p->jvex==j)
{
p=p->ilink;
if(p&&p->ivex==i)
returnp->jvex;
elseif(p&&p->jvex==i)
returnp->jvex;
}
if(p&&p->ivex==j&&p->jvex==i)
{
p=p->jlink;
if(p&&p->ivex==i)
returnp->jvex;
elseif(p&&p->jvex==i)
returnp->jvex;
}
return-1;
}
//------------------------------------队列的操作
intvisite[NUM];//访问标志数组
int(*VisitFunc)(VertexTypev);
voidDFS(AMLGraphG,intv)
{
intj;
EBox*p;
VisitFunc(G.adjmulist[v].data);
visite[v]=1;//该顶点已经被访问
p=G.adjmulist[v].firstedge;
while(p)
{
j=p->ivex==v?
p->jvex:
p->ivex;
if(!
visite[j])
DFS(G,j);
p=p->ivex==v?
p->ilink:
p->jlink;
}
}
//深度优先遍历图
voidDFSTraverse(AMLGraphG,int(*Visit)(VertexType))
{
intv,start;
VisitFunc=Visit;
for(v=0;vvisite[v]=0;
cout<<"请输入你要开始进行查找的位置:
";
cin>>start;
cout<<"按广深度优先搜索的结果是:
"<for(v=start;v{
if(v>=G.vexnum)
{
for(v=0;v{
if(!
visite[v])
DFS(G,v);
}//内层for
}//if
else
{
if(!
visite[v])
DFS(G,v);
}//else
}//外层for
cout<<"\b\b\b";
cout<}
//队列的初始化
intInitQueue(LinkQueue*Q)
{
(*Q).front=(*Q).rear=(QueuePtr)malloc(sizeof(QNode));
if(!
(*Q).front)
exit(0);
(*Q).front->next=NULL;
return1;
}
//判断队列是否为空,为空则返回1,否则返回0
intQueueEmpty(LinkQueueQ)
{
if(Q.front==Q.rear)
return1;
else
return0;
}
//向队列中插入元素
intEnQueue(LinkQueue*Q,QElemTypee)
{
QueuePtrp=(QueuePtr)malloc(sizeof(QNode));
if(!
p)
exit(0);
p->data=e;
p->next=NULL;
(*Q).rear->next=p;
(*Q).rear=p;
return1;
}
//若队列不为空,则删除对头元素,并返回1;否则返回0
intDeQueue(LinkQueue*Q,QElemType*e)
{
QueuePtrp;
if((*Q).front==(*Q).rear)
return0;
p=(*Q).front->next;
*e=p->data;
(*Q).front->next=p->next;
if((*Q).rear==p)
(*Q).rear=(*Q).front;
free(p);
return1;
}
//广度优先非递归遍历图G
voidBFSTraverse(AMLGraphG,int(*Visit)(VertexType))
{
intu,v,w,start=0;
VertexTypew1,u1;
LinkQueueQ;
for(v=0;vvisite[v]=0;
InitQueue(&Q);
cout<<"请输入你要开始进行查找的位置:
";
cin>>start;
cout<<"按广度优先搜索的结果是:
"<for(v=start;v{
if(!
visite[v])
{
visite[v]=1;
Visit(G.adjmulist[v].data);
EnQueue(&Q,v);//v入队列
while(!
QueueEmpty(Q))
{
DeQueue(&Q,&u);
strcpy(u1,*GetVex(G,u));
for(w=FirstAdjVex(G,u1);w>=0;w=NextAdjVex(G,u1,strcpy(w1,*GetVex(G,w))))
if(!
visite[w])
{
visite[w]=1;
Visit(G.adjmulist[w].data);
EnQueue(&Q,w);
}
}
}
}//for
InitQueue(&Q);
for(v=0;v{
if(!
visite[v])
{
visite[v]=1;
Visit(G.adjmulist[v].data);
EnQueue(&Q,v);//v入队列
while(!
QueueEmpty(Q))
{
DeQueue(&Q,&u);
strcpy(u1,*GetVex(G,u));
for(w=FirstAdjVex(G,u1);w>=0;w=NextAdjVex(G,u1,strcpy(w1,*GetVex(G,w))))
if(!
visite[w])
{
visite[w]=1;
Visit(G.adjmulist[w].data);
EnQueue(&Q,w);
}
}
}
}//for
cout<<"\b\b\b";
cout<}
//把边的访问标记设置为0,即未被访问
voidMarkUnVisited(AMLGraphG)
{
inti;
EBox*p;
for(i=0;i{
p=G.adjmulist[i].firstedge;
while(p)
{
p->mark=0;
if(p->ivex==i)
p=p->ilink;
else
p=p->jlink;
}
}
}
//显示构造的无向图(包括定点数、顶点、边数、边)
voidDisplay(AMLGraphG)
{
inti;
EBox*p;
MarkUnVisited(G);
cout<";
for(i=0;icout<cout<<";"<"<for(i=0;i{
p=G.adjmulist[i].firstedge;
while(p)
if(p->ivex==i)
{
if(!
p->mark)
{
cout<"<jvex].data<<"";
p->mark=1;//已经被访问过了
}
p=p->ilink;
}
else
{
if(!
p->mark)
{
cout<ivex].data<<"-->"<p->mark=1;//已经被访问过了
}
p=p->jlink;
}
cout<}
}
intVisit(VertexTypev)
{
cout<";
return1;
}
intmain()
{
intflag=1,control,YES=0;
AMLGraphg;
while(flag)
{
cout<<"\t\t-----------------------------------------------------"<cout<<"\t\t-------------请输入你要进行的操作:
------------------"<cout<<"\t\t-----------1.创建无向图||2.打印无向图||----------"<cout<<"\t\t-----------3.深度优先搜索||4.广度优先搜索||----------"<cout<<"\t\t-----------0.退出系统--------------------------------"<cout<<"\t\t-----------------------------------------------------"<cin>>control;
switch(control)
{
case1:
YES=CreateGraph(g);
break;
case2:
if(YES)
Display(g);
else
{
cout<<"请先创建无向图,再选择此项"<}
break;
case3:
if(YES)
{
DFSTraverse(g,Visit);
}
else
{
cout<<"请先创建无向图,再选择此项"<}
break;
case4:
if(YES)
{
BFSTraverse(g,Visit);
}
else
{
cout<<"请先创建无向图,再选择此项"<}
break;
case0:
flag=0;
break;
}//switch
}//while
return0;
}
四、程序清单
代码运行结果截图:
主页面:
1.创建无向图:
输入6个顶点、9条边,如图:
2.打印无向图:
3.深度优先搜索
4.广度搜索
五、总结
参考资料
[1]殷人昆.《数据结构(用面向对象方法与c++语言描述)》清华大学出版社
[2]严蔚敏、吴伟民.《数据结构(C语言版)》清华大学出版社