实验四 图的构造与遍历
l 实验目的
1、图的的定义和遍历
(1)掌握图的邻接矩阵、邻接表的表示方法。
(2)掌握建立图的邻接矩阵的算法。
(3)掌握建立图的邻接表的算法。
(4)加深对图的理解,逐步培养解决实际问题的能力。
l 实验内容
1、图的定义和遍历
(一)基础题
1、编写图基本操作函数:
(1)CreateALGraph(ALGraph &G) 建立无向图的邻接表表示;
(2)LocateVex(ALGraph &G,char v)图查找信息;
(3)DFSTraverse(ALGraph &G)图的深度遍历操作
(4)BFSTraverse(ALGraph &G)图的广度优先遍历
(5)Create(MGraph &G)邻接矩阵的创建
2、调用上述函数实现下列操作:
(1)建立一个图的邻接矩阵和图的邻接表;
(2)采用递归深度优先遍历输出图的邻接矩阵;
(3)采用递归深度优先输出图的邻接表;
(4)采用图的广度优先遍历输出图的邻接表;
(5)采用图的广度优先遍历输出图的邻接表。
(二)提高题-
【问题描述】设某城市有n个车站,并有m条公交线路连接这些车站。假设这些公交车站都是单向的,这n个车站被顺序编号为0~n-1。在本程序中输入该城市的公交线路数,车站个数以及各公交线路上各站的编号。
【实现要求】求得从站0出发乘公交车至站n-1的最少换车次数。
l 实验结果
1、图的定义和遍历
(一)基础题
(1)画出数据结构基本运算的流程图
(2)程序运行主要结果截图
(3)程序源代码
#include<stdio.h> #include<stdlib.h> typedef struct ArcNode { int adjvex; //邻接点域 struct ArcNode *nextarc; //指向下一个邻接点的指针域 int weight; }ArcNode;//边结点 typedef struct VNode { char vertex; //顶点域 ArcNode *firstarc;//第一条边的指针 }VNode,AdjList[10];//顶点结点向量 typedef struct { AdjList adjlist; int vexnum,arcnum; }ALGraph; //图的邻接矩阵 typedef struct { int adj; }AdjMatrix[10][10]; typedef struct { int vexs[10]; AdjMatrix arcs; int vexnum,arcnum; }MGraph; int LocateVex(ALGraph &G,char v)//查找顶点信息 { int k,j=0; for(k=0;k<G.vexnum;k++) if(G.adjlist[k].vertex==v) { j=k; break; } return j; } void CreateALGraph(ALGraph &G) {//建立无向图的邻接表表示 int i,j,k,w; char v1,v2; ArcNode *s; printf("请输入顶点数和边数(vexnum,arcnum):"); scanf("%d,%d",&G.vexnum,&G.arcnum); for(i=0;i<G.vexnum;i++) {//建立顶点表 getchar(); printf("请输入第%d顶点信息:",i+1); scanf("%c",&G.adjlist[i].vertex);//读入顶点信息 G.adjlist[i].firstarc=NULL;//边表置为空表 } for(k=0;k<G.arcnum;k++) {//建立边表 getchar(); printf("请输入第%d边的顶点对序号和边的权值(v1,v2,w):",k+1); scanf("%c,%c,%d",&v1,&v2,&w); j=LocateVex(G,v2); i=LocateVex(G,v1); s=(ArcNode*)malloc(sizeof(ArcNode)); //生成边表结点 s->adjvex=j;//邻接点序号为j s->weight=w;//权值 s->nextarc=G.adjlist[i].firstarc; G.adjlist[i].firstarc=s; //将新结点*s插入顶点vi的边表头部 //若图为无向图则加上下面的四句代码,若图为有向图则注释下面的四句代码 s=(ArcNode*)malloc(sizeof(ArcNode)); s->adjvex=i; s->weight=w; s->nextarc=G.adjlist[j].firstarc; G.adjlist[j].firstarc=s; } } bool visited[20]; int v; void DFS(ALGraph &G,int v)//深度遍历输出 { visited[v]=true; printf("%c ",G.adjlist[v].vertex); ArcNode *w; for(w=G.adjlist[v].firstarc;w!=NULL;w=w->nextarc) if(!visited[w->adjvex]) DFS(G,w->adjvex); } void DFSTraverse(ALGraph &G)//图的深度遍历操作 { for(v=0;v<G.vexnum;v++) visited[v]=false; for(v=0;v<G.vexnum;v++) if(!visited[v]) DFS(G,v); } //队列 typedef struct QNode { int data; struct QNode *next; }QNode,*QueuePtr; typedef struct { QueuePtr front; QueuePtr rear; }LinkQueue; void InitQueue(LinkQueue &Q)//构造一个空队列 Q { Q.rear=Q.front=(QueuePtr)malloc(sizeof(QNode)); Q.front->next=NULL; } void EnQueue(LinkQueue &Q,int e)//入队 { QNode *p; p=(QueuePtr)malloc(sizeof(QNode)); p->data=e; p->next=NULL; Q.rear->next=p; Q.rear=p; } void DeQueue(LinkQueue &Q,int &e2) {//出队 QNode *p; p=Q.front->next; e2=p->data; Q.front->next=p->next; if(Q.rear==p) Q.rear=Q.front; free(p); } bool visited1[20]; void BFSTraverse(ALGraph &G)//图的广度优先遍历 { for(v=0;v<G.vexnum;v++) visited1[v]=false; LinkQueue Q; InitQueue(Q); for(v=0;v<G.vexnum;v++) if(!visited1[v]) { visited1[v]=true; printf("%c ",G.adjlist[v].vertex); EnQueue(Q,v); int u; ArcNode *w; while(Q.front!=Q.rear) { DeQueue(Q,u); for(w=G.adjlist[u].firstarc;w!=NULL;w=w->nextarc) if(!visited1[w->adjvex]) { visited1[w->adjvex]=true; printf("%c ",G.adjlist[w->adjvex].vertex); EnQueue(Q,w->adjvex); } } } } void display(ALGraph &G)//输出图的顶点信息 { printf("建立的邻接表位:\n"); int i; for(i=0;i<G.vexnum;i++) { if(G.adjlist[i].firstarc!=NULL) { printf("%c->",G.adjlist[i].vertex); ArcNode *p; p=G.adjlist[i].firstarc; while(p!=NULL) { printf("%d->",p->adjvex); p=p->nextarc; } printf("NULL\n"); } else { printf("%c->NULL\n",G.adjlist[i].vertex); } } } int LocateVex(MGraph &G,int v) { int k,j=0; for(k=0;k<G.vexnum;k++) if(G.vexs[k]==v) { j=k; break; } return j; } void Create(MGraph &G) { int i,j,k; int v1=0,v2=0,w=0; printf("请输入图的顶点数:"); scanf("%d",&G.vexnum); printf("请输入图的边数:"); scanf("%d",&G.arcnum); for(i=0;i<G.vexnum;i++) G.vexs[i]=i+1; for(i=0;i<G.vexnum;i++) for(j=0;j<G.vexnum;j++) G.arcs[i][j].adj=0; for(k=0;k<G.arcnum;k++) { printf("请输入一条边依附的顶点v1,v2及权值(v1,v2,w):"); scanf("%d,%d,%d",&v1,&v2,&w); i=LocateVex(G,v1); j=LocateVex(G,v2); G.arcs[i][j].adj=w; } } void display(MGraph &G) { int i,j; for(i=0;i<G.vexnum;i++) { for(j=0;j<G.vexnum;j++) printf("%d",G.arcs[i][j].adj); printf("\n"); } } int main() { int z; printf("请输入选择:\n-1-建立图的邻接矩阵\n-2-建立图的邻接表\n"); scanf("%d",&z); if(z==1) { MGraph G; Create(G); display(G); scanf("%d",&z); } if(z==2) { ALGraph G; CreateALGraph(G);//建立无向图邻接表 display(G);//输出图的的顶点信息 printf("\n\n"); printf("图的深度遍历为:\n"); DFSTraverse(G); printf("\n"); printf("\n\n"); printf("图的广度遍历为:"); BFSTraverse(G); printf("\n"); } }
(二)提高题
(1)画出数据结构基本运算的流程图
(2)程序运行主要结果截图
(3)程序源代码

1 #include<stdio.h> 2 3 #define M 20 4 5 #define N 50 6 7 int a[N+1]; 8 9 int g[N][N]; 10 11 int dist[N]; 12 13 int m=0,n=0; 14 15 void buildG()//建图 16 17 { 18 19 int i,j,k,sc,dd; 20 21 while(1) 22 23 { 24 25 printf("输入公交线路数[1-%d],公交站数[1-%d]\n",M,N); 26 27 scanf("%d %d",&m,&n); 28 29 if(m>=1&&m<=M&&n>=1&&n<=N) 30 31 break; 32 33 } 34 35 for(i=0;i<n;i++) 36 37 for(j=0;j<n;j++) 38 39 g[i][j]=0; 40 41 for(i=0;i<m;i++) 42 43 { 44 45 printf("沿第%d条公交车线路前进方向的各站编号(0<=编号<=%d,-1结束):\n",i+1,n-1); 46 47 sc=0; 48 49 while(1) 50 51 { 52 53 scanf("%d",&dd); 54 55 if(dd==-1) 56 57 break; 58 59 if(dd>=0&&dd<n) 60 61 a[sc++]=dd; 62 63 } 64 65 a[sc]=-1; 66 67 for(k=1;a[k]>=0;k++) 68 69 for(j=0;j<k;j++) 70 71 g[a[j]][a[k]]=1; 72 73 } 74 75 } 76 77 int minLen() 78 79 { 80 81 int j,k; 82 83 for(j=0;j<n;j++) 84 85 dist[j]=g[0][j]; 86 87 dist[0]=1; 88 89 while(1) 90 91 { 92 93 for(k=-1,j=0;j<n;j++) 94 95 if(dist[j]>0&&(k==-1||dist[j]<dist[k])) 96 97 k=j; 98 99 if(k<0||k==n-1) 100 101 break; 102 103 dist[k]=-dist[k]; 104 105 for(j=1;j<n;j++) 106 107 if(g[k][j]==1&&(dist[j]==0||-dist[k]+1<dist[j])) 108 109 dist[j]=-dist[k]+1; 110 111 } 112 113 j=dist[n-1]; 114 115 return(k<0?-1:j-1); 116 117 } 118 119 int main() 120 121 { 122 123 int t; 124 125 buildG(); 126 127 t=minLen(); 128 129 if(t<0) 130 131 printf("无解!\n"); 132 133 else 134 135 printf("从0号站到%d站需换车%d次\n",n-1,t); 136 137 }