TopSort(拓撲排序)、求關鍵路徑
阿新 • • 發佈:2019-02-07
程式小白,希望和大家多交流,共同學習
//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;
}