1. 程式人生 > >TopSort(拓撲排序)、求關鍵路徑

TopSort(拓撲排序)、求關鍵路徑

程式小白,希望和大家多交流,共同學習

//TopSort拓撲排序
#include<iostream>
#include<string>
#include<queue>
#define MAX_VN 50
#define INF 32767
using namespace std;
typedef string VertexData;

struct ArcNode{
    int adjvex;
    int weight;
    ArcNode *nextArc;
};

struct Vertex{
    VertexData data;
    ArcNode *firstArc;
};

struct
AdjList{ Vertex vertex[MAX_VN]; int verNum, arcNum; }; void createAdjList(AdjList &G); int locateVertex(AdjList &G, VertexData data); void outputAdjList(AdjList &G); void topOrder(const AdjList &G,int *order); void printTopOder(const AdjList &G,int *order); //關鍵路徑 void criticalPath(const
AdjList &G); int main(){ /* 9 11 V0 V1 V2 V3 V4 V5 V6 V7 V8 V0 V1 6 V0 V2 4 V0 V3 5 V1 V4 1 V2 V4 1 V3 V5 2 V4 V6 9 V4 V7 7 V5 V7 4 V6 V8 2 V7 V8 4 */ AdjList G; createAdjList(G); outputAdjList(G); cout << "TopOrder:" << endl; int *order = new int[G.verNum + 1]; topOrder(G, order); printTopOder(G, order); criticalPath(G); return
0; } void createAdjList(AdjList &G){ cout << "輸入頂點個數和弧的條數:"; cin >> G.verNum >> G.arcNum; cout << "輸入頂點資訊:"; for (int i =1; i <= G.verNum; i++){ cin >> G.vertex[i].data; G.vertex[i].firstArc = NULL;//初始化 } cout << "輸入各條弧的資訊:"; VertexData u, v; int w; int i, j; for (int k = 1; k <= G.arcNum; k++){ cin >> u >> v >> w; i = locateVertex(G, u); j = locateVertex(G, v); ArcNode *p = new ArcNode; p -> weight = w; p -> adjvex = j; p -> nextArc = G.vertex[i].firstArc; G.vertex[i].firstArc = p; } } int locateVertex(AdjList &G, VertexData data){ for (int i = 1; i <= G.verNum; i++){ if (G.vertex[i].data == data){ return i; } } return -1; } void outputAdjList(AdjList &G){ for (int i = 1; i <= G.verNum; i++){ cout << i << " "; cout << G.vertex[i].data << " -> "; ArcNode *p = G.vertex[i].firstArc; while (p){ cout << p -> adjvex << " " << p -> weight << " -> "; p = p -> nextArc; } cout << " ^" << endl; } } void topOrder(const AdjList &G, int *order){ //初始化入度為零 int *inDegrees = new int[G.verNum + 1]; for (int i = 1; i <= G.verNum; i++){ inDegrees[i] = 0; } //按照G的結構更新度 ArcNode *p; for (int i = 1; i <= G.verNum; i++){ p = G.vertex[i].firstArc; while (p){ int j = p -> adjvex; inDegrees[j]++; p = p -> nextArc; } } //將度為0的加入佇列 queue<int> q; for (int i = 1; i <= G.verNum; i++){ if (inDegrees[i] == 0){ q.push(i); } } //按照出佇列的方式,將度為0的入棧,並將此頂點的鄰接點的度減一 //根據出棧順序,將每次出棧的頂點記錄在order中 int k = 0; while (k < G.verNum){ int z = q.front(); q.pop();//返回棧頂元素之後要出棧 order[++k] = z; p = G.vertex[z].firstArc; while (p){ int j = p -> adjvex; inDegrees[j]--; if (inDegrees[j] == 0){ q.push(j); } p = p -> nextArc; } } delete []inDegrees; } void printTopOder(const AdjList &G, int *order){ for (int i = 1; i <= G.verNum; i++){ cout << G.vertex[order[i]].data << " "; } cout << endl; } void criticalPath(const AdjList &G){ int n = G.verNum; int *ve = new int[n + 1]; int *vl = new int[n + 1]; int *order = new int[n + 1]; topOrder(G, order); for (int i = 1; i <= n; i++){ cout << G.vertex[order[i]].data << " "; } cout << endl; //ve for (int i = 1; i <= n; i++){ ve[i] = 0; } for (int i = 1; i <= n; i++){ int u = order[i]; ArcNode *p = G.vertex[u].firstArc; while (p){ int j = p -> adjvex; if (ve[j] < ve[u] + p -> weight){ ve[j] = ve[u] + p -> weight; } p = p -> nextArc; } } for (int i = 1; i <= n; i++){ printf("%-3d", ve[i]); } cout << endl; //vl for (int i = 1; i <= n; i++){ vl[i] = ve[n]; } for (int i = n - 1; i >= 1; i--){ int u = order[i]; ArcNode *p = G.vertex[u].firstArc; while (p){ int j = p -> adjvex; if (vl[u] > vl[j] - p -> weight){ vl[u] = vl[j] - p -> weight; } p = p -> nextArc; } } for (int i = 1; i <= n; i++){ printf("%-3d", vl[i]); } cout << endl; //關鍵路徑 //其實ve和vl都是在儲存關鍵路徑,最大ve是加法,加的最多所以最大,那麼加的最多的是關鍵路徑 //最小vl是減法,減的最多所以最小,那麼減的最多的是關鍵路徑 cout << "關鍵路徑是:"; int ee, el; for (int i = 1; i < n; i++){ int u = order[i]; ee = ve[u]; ArcNode *p = G.vertex[u].firstArc; while (p){ int j = p -> adjvex; el = vl[j] - p -> weight; if (ee == el){ cout << G.vertex[u].data << " -> " << G.vertex[j].data << endl; } p = p -> nextArc; } } delete []ve; delete []vl; delete []order; }