//入度 顶点编号
0 0 11 5 4 -1
0 1 8 4 2 -1
2 2 9 6 5 -1
0 3 13 3 2 -1
2 4 7 -1
3 5 12 8 -1
1 6 5 -1
2 7 -1
2 8 7 -1
2 9 11 10 -1
1 10 13 -1
2 11 -1
1 12 9 -1
2 13 -1
前提: 有向无环图
在一个表示工程的有向图中,用顶点表示活动,用弧表示活动之间的优先关系,这样的有向图为顶点表示活动的网,称为AOV网(Activity On Vertex Network).
AOV中的弧表示活动之间存在着制约关系 比如:要想上中学,必须先上小学 这样小学作为弧的弧尾,中学作为弧的弧头。
对于拓扑排序的构造过程,有两个结果。
1.如果此网的全部顶点被输出,则说明是不存在环的AOV网。
2.如果输出的顶点数量少了,哪怕是少一个,说明网存在环,不是AOV网。
#include <iostream>
#include <stack>
#include <string>
#include <vector>
using namespace std;
#define MAXVEX 14
int edgeNum;
vector<vector<int> > res;
//边表节点
struct EdgeNode {
int adjvex; //该顶点的索引
struct EdgeNode* next;
EdgeNode(int data) {
this->adjvex = data;
this->next = NULL;
}
};
//出发顶点表节点
typedef struct VertexNode {
int in; //顶点入度数
int data; //顶点编号
EdgeNode* firstedge; //边表头节点
EdgeNode* endedge; //边表尾节点
}VertexNode, AdjList[MAXVEX];
//将 边表节点和顶点表 一起打包
struct Graph {
AdjList adjList;
int numVertexes, numEdges;
Graph() {
this->numVertexes = MAXVEX;
this->numEdges = edgeNum;
}
};
void init(AdjList& adjlist) {
for (int i = 0; i < MAXVEX; i++) {
//初始虚拟头结点的后继一定要为NULL
adjlist[i].firstedge = NULL;
//输入顶点表的入度 和 顶点编号(不是索引号)
cin >> adjlist[i].in;
cin >> adjlist[i].data;
int index;
//输入边表节点中 顶点的"索引"
while (cin >> index && index != -1) {
edgeNum++;
//节点打包 并用倒插法插入到当前的虚拟头节点后
EdgeNode* v = new EdgeNode(index);
v->next = adjlist[i].firstedge;
adjlist[i].firstedge = v;
}
}
}
//打印邻接表
void println(AdjList adjlist) {
cout << "*************************************" << endl;
cout << "邻接表 :" << endl;
for (int i = 0; i < MAXVEX; i++) {
cout << adjlist[i].in << " V" << adjlist[i].data << "-> ";
EdgeNode* v = adjlist[i].firstedge;
while (v != NULL) {
cout << v->adjvex << "->";
v = v->next;
}
cout << "NULL" << endl;
}
cout << "*************************************" << endl;
}
bool TopologicalSort(AdjList adjlist) {
//以不同的顺序初始入栈
for (int j = 0; j < MAXVEX; j++) {
vector<int> vec;
stack<VertexNode> s;
int num = 0;
//最初入度为0的节点入栈 即不需要前置条件即可的
for (int i = j; ; i++) {
i = i % MAXVEX;
//编号为i的节点入度为0 入栈
if (adjlist[i].in == 0)
s.push(adjlist[i]);
num++;
if (num == MAXVEX)
break;
}
//逐一出栈 将出栈后的顶点的 弧头链接的顶点入度-1
while (!s.empty()) {
VertexNode tex = s.top();
vec.push_back(tex.data);
EdgeNode* e = tex.firstedge;
s.pop();
while (e != NULL) {
//入度数减1 如果为0 通过索引找到节点
adjlist[e->adjvex].in--;
if (adjlist[e->adjvex].in == 0)
s.push(adjlist[e->adjvex]);
e = e->next;
}
}
如果顶点数不等于总数 说明存在环 即不存在拓扑排序
if (vec.size() == MAXVEX) {
res.push_back(vec);
}
}
if (res.size())
return true;
return false;
}
void println(vector<vector<int> > v) {
cout << "*************************************" << endl;
cout << "拓扑序列 : ";
for (int i = 0; i < v.size(); i++) {
for (int j = 0; j < v[i].size(); j++) {
cout << v[i][j];
if (j < v[i].size() - 1)
cout << " -> ";
}
cout << endl;
}
cout << "*************************************" << endl;
}
int main()
{
AdjList adjlist;
init(adjlist);
println(adjlist);
bool t = TopologicalSort(adjlist);
if (t)
println(res);
else
cout << "无路径" << endl;
}