实验五图的操作及应用.docx
《实验五图的操作及应用.docx》由会员分享,可在线阅读,更多相关《实验五图的操作及应用.docx(14页珍藏版)》请在冰豆网上搜索。
实验五图的操作及应用
实验五:
图的操作及应用
实验学时:
4
实验类型:
综合型
一、实验目的
1.理解图的逻辑结构和物理结构;
2.掌握图的邻接矩阵和邻接表存储表示的实现方法;
3.掌握图的深度优先和广度优先遍历算法的实现;
4.掌握拓扑排序算法的实现方法。
二、实验条件
VisualC++6.0
三、实验原理及相关知识
1.图的邻接矩阵和邻接表存储结构的描述;
2.图的邻接矩阵和邻接表存储表示的算法;
3.图的深度优先和广度优先遍历算法;
4.拓扑排序算法。
四、实验步骤
1.实现图的邻接矩阵的存储表示。
2.实现图的邻接表存储表示。
3.实现图的深度优先和广度优先遍历算法。
4.实现拓扑排序算法。
5.调用以上函数实现以下操作:
(1)建立图。
(2)输出基于邻接表存储的深度优先和广度优先遍历序列。
(3)输出有向图的拓扑排序序列。
参考代码:
要求:
补充完整以下代码使其能够运行通过。
#include"stdio.h"
#include"malloc.h"
#include"string.h"
#defineINFINITY10000//用整型最大值代替∞
#defineMAX_VERTEX_NUM20//最大顶点个数
#defineOK1
#defineERROR0
#defineFALSE0
#defineTRUE1
#defineMAXQSIZE100
typedefintQElemType;
typedeffloatVRType;
typedeffloatInfoType;
typedefcharVertexType;
typedefcharVexType;
//============邻接矩阵的定义============
typedefstruct{
VRTypeadj;
InfoTypeinfo;//该弧相关信息的指针(可无)
}ArcCell,AdjMatrix[MAX_VERTEX_NUM][MAX_VERTEX_NUM];
typedefstruct{
VertexTypevexs[MAX_VERTEX_NUM][100];//顶点向量
AdjMatrixarcs;//邻接矩阵
intvexnum,arcnum;//图的当前顶点数和弧数
}MGraph;
//=======================邻接矩阵的定义========
//=================================邻接表的定义=========
typedefstructArcNode{//表结点
intadjvex;//该弧所指向的顶点的位置
structArcNode*nextarc;//指向下一条弧的指针
floatinfo;//网的权值指针
}ArcNode;
typedefstruct{//头结点
VertexTypedata[100];//顶点信息
ArcNode*firstarc;//第一个表结点的地址
}VNode,AdjList[MAX_VERTEX_NUM];
typedefstruct{
AdjListvertices;
intvexnum,arcnum;//图的当前顶点数和弧数
}ALGraph;
intvisited[MAX_VERTEX_NUM];
//=================邻接表的定义=========================
//=========队列定义和基本操作===============
typedefstructQNode1{
QElemTypedata;
structQNode1*next;
}QNode,*QueuePtr;
typedefstruct{//链队列的定义
QElemType*base;
intfront;
intrear;
}SqQueue;
typedefstruct{
QueuePtrfront;
QueuePtrrear;
}LinkQueue;
LinkQueueInitQueue(LinkQueueQ){
Q.front=Q.rear=(QueuePtr)malloc(sizeof(QNode));
if(!
Q.front)
exit
(1);
Q.front->next=NULL;
returnQ;
}
intEnQueue(LinkQueue*Q,QElemTypee){
QueuePtrp;
if(!
(p=(QueuePtr)malloc(sizeof(QNode))))
returnERROR;
p->data=e;
p->next=NULL;
Q->rear->next=p;
Q->rear=p;
returnOK;
}
intDeQueue(LinkQueue*Q,QElemType*e){
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;
}
intQueueEmpty(LinkQueue*Q){
if(Q->front==Q->rear)return1;
elsereturn0;
}
intDestroyQueue(LinkQueue*Q){
while(Q->front){
Q->rear=Q->front->next;
free(Q->front);
Q->front=Q->rear;
}
returnOK;
}
//===================队列定义和基本操作===============
intLocateVex(MGraphG,char*vert)
{inti;
for(i=0;iif(strcmp(G.vexs[i],vert)==0)
returni;
return-1;
}
intLocateVex1(ALGraphG,char*vert)
{inti;
for(i=0;iif(strcmp(G.vertices[i].data,vert)==0)
returni;
return-1;
}
MGraphCreateGraph_UDN(MGraphG){//建立无向网G的邻接矩阵
inti,j,k;
floatw;
VexTypev1[100],v2[100];
printf("输入顶点数,数边数:
");
scanf("%d%d",&G.vexnum,&G.arcnum);
for(i=0;i{printf("输入第%d个顶点的信息:
",i+1);
scanf("%s",&G.vexs[i]);
}
for(i=0;ifor(j=0;jG.arcs[i][j].adj=INFINITY;
for(k=0;kprintf("输入第%d条边依附的两个顶点和边上的权值:
",k+1);
scanf("%s%s%f",&v1,&v2,&w);
//查询两个顶点在图中存储的位置
i=LocateVex(G,v1);
j=LocateVex(G,v2);
if(i==-1||j==-1)
{printf("输入的边不正确\n");return;}
G.arcs[i][j].adj=w;
G.arcs[j][i].adj=G.arcs[i][j].adj;
}
returnG;
}
ALGraphCreateALGraph_UDN(ALGraphG)//建立无向网G的邻接表
{
inti,j,k;
floatw;
ArcNode*p;
VexTypev1[100],v2[100];
printf("输入顶点数,数边数:
");
scanf("%d%d",&(G.vexnum),&(G.arcnum));/*读入顶点数和边数*/
for(i=0;i{
printf("输入第%d个顶点的信息:
",i+1);
scanf("%s",&(G.vertices[i].data));/*读入顶点信息*/
G.vertices[i].firstarc=NULL;/*顶点的边表头指针设为空*/
}
for(k=0;k{
printf("输入一条边依附的两个顶点和边上的权值:
");
scanf("%s%s%f",&v1,&v2,&w);/*读入边的顶点对应序号*/
i=LocateVex1(G,v1);
j=LocateVex1(G,v2);
if(i==-1||j==-1)
{printf("输入的边不正确\n");return;}
p=(ArcNode*)malloc(sizeof(ArcNode));/*生成新边表结点p*/
p->adjvex=j;/*邻接点序号为j*/
p->info=w;
p->nextarc=G.vertices[i].firstarc;/*将新边表结点p插入到顶点Vi的链表头部*/
G.vertices[i].firstarc=p;
p=(ArcNode*)malloc(sizeof(ArcNode));/*生成新边表结点p*/
p->adjvex=i;/*邻接点序号为i*/
p->info=w;
p->nextarc=G.vertices[j].firstarc;/*将新边表结点p插入到顶点Vj的链表头部*/
G.vertices[j].firstarc=p;
}
returnG;
}/*CreateALGraph*/
VisitFunc(char*ch)//输出顶点的信息
{
printf("%s",ch);
}
voidDFS(ALGraphG,intv){
intj;
ArcNode*p;
VisitFunc(G.vertices[v].data);//访问第v个顶点
visited[v]=TRUE;//设置访问标志为TRUE(已访问)
for(p=G.vertices[v].firstarc;p;p=p->nextarc)
{
j=p->adjvex;
if(!
visited[j])DFS(G,j);
}
}
voidDFSTraverse(ALGraphG){//图的深度优先遍历算法
intv;
for(v=0;vvisited[v]=FALSE;//访问标志数组初始化(未被访问)
for(v=0;vif(!
visited[v])
DFS(G,v);//对尚未访问的顶点调用DFS
}
voidBFSTraverse(ALGraphG)//图的广度优先遍历算法
{
intv,j,u;
ArcNode*p;
LinkQueueQ;
Q=InitQueue(Q);//置空的辅助队列Q
for(v=0;vvisited[v]=FALSE;//置初值
for(v=0;vif(!
visited[v]){
visited[v]=TRUE;//设置访问标志为TRUE(已访问)
VisitFunc(G.vertices[v].data);
EnQueue(&Q,v);//v入队列
while(!
QueueEmpty(&Q)){
DeQueue(&Q,&u);//队头元素出队并置为u
for(p=G.vertices[u].firstarc;p;p=p->nextarc)
{
j=p->adjvex;
if(!
visited[j])
{visited[j]=TRUE;
VisitFunc(G.vertices[j].data);
EnQueue(&Q,j);
}
}
}
}
DestroyQueue(&Q);
}
//实现建立有向网的邻接矩阵和邻接表的函数
MGraphCreateGraph_DN(MGraphG){//建立有向网G的邻接矩阵
{
}
ALGraphCreateALGraph_DN(ALGraphG)//建立有向网G的邻接表
{
}
Print_MGraph(MGraphG)//输出图的邻接矩阵表示
{
inti,j;
for(i=0;i{for(j=0;jprintf("%f",G.arcs[i][j].adj);/*邻接矩阵*/
printf("\n");
}
}
Print_ALGraph(ALGraphG)//输出图的邻接表表示
{
inti,j;
ArcNode*p;
for(i=0;i{
printf("%s",G.vertices[i].data);/*顶点信息*/
p=G.vertices[i].firstarc;
while(p!
=NULL)/*表节点信息*/
{
printf("->%s",G.vertices[p->adjvex].data);
p=p->nextarc;
}/*顶点的边表头指针设为空*/
printf("\n");
}
}
voidFindInDegree(ALGraphG,int*indegree)
{
inti,k;ArcNode*p;
for(i=0;i{
for(p=G.vertices[i].firstarc;p;p=p->nextarc){
{k=p->adjvex;indegree[k]++;}
}
}
}
//===================拓扑排序==============================
intTopologicalSort(ALGraphG){
//有向图G采用邻接表存储结构。
//若G无回路,则输出G的顶点的一个拓扑序列并返回OK,否则ERROR。
intSqStack[MAX_VERTEX_NUM],top=0;
intcount,k,i;
ArcNode*p;
intindegree[MAX_VERTEX_NUM];
for(i=0;iFindInDegree(G,indegree);//对各顶点求入度indegree[0..vernum-1]
for(i=0;iif(!
indegree[i]){SqStack[top]=i;top++;}//入度为0者进栈
count=0;//对输出顶点计数
while(top){
top--;
i=SqStack[top];
printf("%d->",G.vertices[i].data);++count;//输出i号顶点并计数
for(p=G.vertices[i].firstarc;p;p=p->nextarc){
k=p->adjvex;//对i号顶点的每个邻接点的入度减1
if(!
(--indegree[k])){SqStack[top]=k;top++;}//若入度减为0,则入栈
}
}
if(count");returnERROR;}//该有向图有回路
elsereturnOK;
}//TopologicalSort
//======================拓扑排序=====================
main()
{
MGraphG1,G3;
ALGraphG2,G4;
intP[MAX_VERTEX_NUM][MAX_VERTEX_NUM];
floatD[MAX_VERTEX_NUM];
G1=CreateGraph_UDN(G1);
G2=CreateALGraph_UDN(G2);
Print_ALGraph(G2);
DFSTraverse(G2);
BFSTraverse(G2);
//建立有向网G3的邻接矩阵
//建立有向网G4的邻接表
//输出有向网G3邻接矩阵
//输出有向网G4邻接表
//深度优先和广度优先遍历有向网G4
//TopologicalSort(G4);//求邻接表表示的有向图的拓扑排序
}
五、思考题及其它
基于邻接矩阵的图的深度和广度优先遍历算法;
最小生成树算法。