實驗四 圖的構造與遍歷
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 }