圖的遍歷(dfs、bfs、最短路、最小生成樹、拓撲排序)
阿新 • • 發佈:2019-01-01
程式碼如下:
#include <cstdio> #include <cmath> #include <vector> #include <cstring> #include <algorithm> using namespace std; #define CLR(a,b) memset(a,b,sizeof(a)) #define INF 0x3f3f3f3f #define LL long long #define MAXSIZE 100 bool vis[MAXSIZE+5]; int in[MAXSIZE+11]; //入度 int f[MAXSIZE+11]; //並查集指向根節點 typedef struct { int x,y; int cost; }road[(MAXSIZE*MAXSIZE+MAXSIZE)>>1],Road; typedef struct //鄰接矩陣 { int arcs[MAXSIZE+5][MAXSIZE+5]; int vexnum,arcnum; void init() { CLR(this->arcs,0); this->arcnum = this->vexnum = 0; } }AMGraph; typedef struct ArcNode //鄰接表,頂點序號用數字表示 { int adjvex; struct ArcNode *nextarc; }AdjList[MAXSIZE+5],AdjNode; typedef struct { AdjList vectices; int vexnum,arcnum; //頂點、邊數 void init() //初始化 { for (int i = 1 ; i <= MAXSIZE ; i++) this->vectices[i].nextarc = NULL; this->arcnum = this->vexnum = 0; } void Insert(int pos,AdjNode &t) //在pos點後連線t節點 { t.nextarc = this->vectices[pos].nextarc; this->vectices[pos].nextarc = &t; } }ALGraph; typedef struct Queue //佇列 { int data; struct Queue *next; struct Queue *end; //佇列末節點 void init() { this->end = this; this->next = NULL; } int GetTop() { return this->next->data; } bool Empty() { if (this->next == NULL) return true; return false; } void Pop() { Queue *t = this->next; this->next = this->next->next; free(t); if (this->Empty()) //如果佇列為空,隊尾指標指向自己 this->end = this; } void Push(int x) { Queue *t; t = (Queue *)malloc(sizeof(Queue)); t->data = x; t->next = NULL; this->end->next = t; this->end = t; } }Queue; void dfsSearch(AMGraph &mm,int pos) //遞迴求DFS { printf ("%d ",pos); vis[pos] = true; for (int i = 1 ; i <= mm.vexnum ; i++) { if (!vis[i] && mm.arcs[pos][i]) dfsSearch(mm,i); } } void DFS(AMGraph &mm) { printf ("該無向圖的DFS序為:"); dfsSearch(mm,1); puts(""); } void BFS(AMGraph &mm) { printf ("該無向圖的BFS序為:"); CLR(vis,false); Queue q; q.init(); q.Push(1); vis[1] = true; while (!q.Empty()) { int pr = q.GetTop(); q.Pop(); printf ("%d ",pr); for (int i = 1 ; i <= mm.vexnum ; i++) { if (!vis[i] && mm.arcs[pr][i]) //沒有遍歷過,並且存在邊 { q.Push(i); vis[i] = true; } } } printf ("\n"); } void dijkstra(AMGraph &mm) { CLR(vis,false); int dis[MAXSIZE+5]; CLR(dis,INF); dis[1] = 0; while (1) { int v = -1; for (int i = 1 ; i <= mm.vexnum ; i++) { if (!vis[i] && (v == -1 || dis[i] < dis[v])) v = i; } if (v == -1) break; vis[v] = true; //標記 for (int i = 1 ; i <= mm.vexnum ; i++) { if (vis[i] == false && mm.arcs[v][i]) dis[i] = min(dis[i] , dis[v] + mm.arcs[v][i]); } } printf ("%d\n",dis[mm.vexnum] == INF ? -1 : dis[mm.vexnum]); //不存在最短路徑輸入-1 } void ShortestRoad(AMGraph &mm) { printf ("從1點到%d點的最短路徑為(不存在輸出-1):",mm.vexnum); dijkstra(mm); } int find(int x) //遞迴尋根節點並路徑壓縮 { if (x != f[x]) f[x] = find(f[x]); return f[x]; } bool join(int x,int y) //合併節點 { int fx,fy; fx = find(x); fy = find(y); if (fx != fy) { f[fx] = fy; return true; } return false; } bool cmp(Road a,Road b) { return a.cost < b.cost; } void Kruskal(AMGraph &mm) { for (int i = 1 ; i <= mm.vexnum ; i++) f[i] = i; //初始化並查集根節點 int ant = 0; road d; for (int i = 1 ; i < mm.vexnum ; i++) { for (int j = i + 1 ; j <= mm.vexnum ; j++) { if (mm.arcs[i][j]) { d[ant].x = i; d[ant].y = j; d[ant++].cost = mm.arcs[i][j]; } } } sort(d,d+ant,cmp); int cost = 0; //最小花費 for (int i = 0 ; i < ant ; i++) { if (join(d[i].x , d[i].y)) cost += d[i].cost; } printf ("%d\n",cost); } void MiniSpanTree(AMGraph &mm) { printf ("最小生成樹的最小花費為:"); Kruskal(mm); } void Topo(ALGraph &am) { printf ("拓撲排序結果為:"); Queue q; q.init(); for (int i = 1 ; i <= am.vexnum ; i++) { if (!in[i]) q.Push(i); } while (!q.Empty()) { int pr = q.GetTop(); printf ("%d ",pr); q.Pop(); in[pr] = -1; AdjNode *t; t = am.vectices[pr].nextarc; while (t != NULL) { in[t->adjvex]--; if (!in[t->adjvex]) q.Push(t->adjvex); t = t->nextarc; } } puts(""); } int main() { int arcnum,vexnum; AMGraph mm; //Matrix map ALGraph am; //Adj map mm.init() , am.init(); printf ("請輸入頂點數的邊數:"); scanf ("%d %d",&vexnum,&arcnum); am.arcnum = mm.arcnum = arcnum; am.vexnum = mm.vexnum = vexnum; printf ("請輸入%d條邊(DFS、BFS、最短路、最小生成樹中存為無向圖 ; 拓撲排序用有向圖):\n",arcnum); for (int i = 1 ; i <= arcnum ; i++) //讀入資料 { int x,y,z; //頂點,邊的權值 scanf ("%d %d %d",&x,&y,&z); mm.arcs[x][y] = mm.arcs[y][x] = z; AdjNode t; t.adjvex = y; t.nextarc = NULL; in[y]++; am.Insert(x,t); //插入鄰接表中 } DFS(mm); BFS(mm); ShortestRoad(mm); MiniSpanTree(mm); Topo(am); return 0; } /* 1 3 1 3 7 1 7 6 1 6 3 1 1 2 1 2 5 1 5 8 1 8 4 1 4 2 1 */