AOV网
表示工程的有向图,一定是个DAG(有向无环)网
拓扑序列
根据AOV网作出的流程顺序
拓扑排序
思路:
标记点的入度,从入度为0的开始,访问一个点,删除它对应的边,更新其他点的入度,重复,直到所有的点全部输出(点没输出完,剩余顶点没有入度为0的顶点,说明可能有环
代码(使用C++
使用了自己写的双向链表式队列,实现待处理拓扑排序点的存放
#include<iostream>
#include <cstring>
using namespace std;
#pragma region //链队列实现广度优先拓扑排序,用栈则会得到深度优先(我取的叫法,不知道别人怎么叫的
struct MyQueNode
{
int data; //将用于存储入度为0的顶点下标
MyQueNode* next;
MyQueNode* prev;
MyQueNode()
{
data = -1;
next = prev = nullptr;
}
MyQueNode(int data_)
{
data = data_;
next = prev = nullptr;
}
};
struct MyQue
{
MyQueNode* head;
MyQueNode* tail;
MyQue()
{
head = tail = nullptr;
}
void push_back(int data_);
void pop();
int front();
bool empty();
};
void MyQue::push_back(int data_)
{
MyQueNode* p = new MyQueNode(data_);
if(tail == nullptr)//链表为空情况
{
head = tail = p;
return;
}
p->prev = tail;
tail->next = p;
tail = p;
}
int MyQue::front()
{
return head->data;
}
void MyQue::pop()
{
MyQueNode* p = head;
if(head==tail)//链表剩一个结点情况(默认不会错误使用pop
tail = nullptr;
head = p->next;
delete p;
}
bool MyQue::empty()
{
return head == nullptr;
}
#pragma endregion
#pragma region //全局变量
const int N = 105;
#pragma endregion
#pragma region //邻接表图的结构体
struct Edge
{
int vexP; //邻接的点的下标
Edge* next; //下一条边
Edge(){ next = nullptr;}
};
struct Vex
{
char val; //顶点字符值
Edge* first; //边链表
Vex(){first = nullptr;}
};
struct Graph
{
int n;
Vex g[N];
int* topo;
void getTopo();
void addEdge(int a, int b);
Graph(){topo =nullptr;}
int find(char c);
};
int Graph::find(char c)
{
for (int i = 0; i < n; i++)
{
if(g[i].val == c)
return i;
}
return -1;
}
void Graph::addEdge(int a, int b)
{
Edge* e = new Edge;
e->vexP = b;
e->next = nullptr;
if( g[a].first )
{
e->next = g[a].first;
}
g[a].first = e;
}
void Graph::getTopo()
{
MyQue q;
if(topo !=nullptr )
delete[] topo;
topo = new int[n];
int* ind = new int[n];
memset(ind,0,sizeof(int)* n);
for (int i = 0; i < n; i++)//记录所有顶点入度
{
Edge* e = g[i].first;
while(e)
{
ind[e->vexP]++;
e = e->next;
}
}
/*
for (int i = 0; i < n; i++)//测试ind正确性
{
cout << g[i].val << " : " << ind[i]<< endl;
}
*/
for (int i = 0; i < n; i++)//找入度为0的顶点
{
if(ind[i] == 0)
{
q.push_back(i);
}
}
for (int i = 0; i < n; i++) //依次取点,刷新入度,直到取完n个点
{
if(q.empty())
{
break;
cout<<"failed!\n";
}
topo[i] = q.front();
q.pop();
Edge* e = g[topo[i]].first;
while(e)
{
ind[e->vexP]--;
if(ind[e->vexP] == 0) //有可能要加入的顶点
q.push_back(e->vexP);
e = e->next;
}
}
delete[] ind ;
ind = nullptr;
}
#pragma endregion
int main()
{
int n,m;
cin >> n >> m;
Graph aov;
aov.n = n;
for (int i = 0; i < n; i++)
{
cin >> aov.g[i].val;
}
for (int i = 0; i < m; i++)
{
int a,b;
char ca,cb;
cin >> ca >> cb;
a = aov.find(ca);
b = aov.find(cb);
aov.addEdge(a,b);
}
/*测试
cout<<"----------------------------\n";
for (int i = 0; i < n; i++)
{
cout << i <<" : " << aov.g[i].val << endl;
}
for (int i = 0; i < n; i++)
{
Edge* e = aov.g[i].first;
while(e)
{
cout << aov.g[i].val << " -> " << aov.g[e->vexP].val <<endl;
e = e->next;
}
}
cout<<"----------------------------\n";
*/
aov.getTopo();
cout<< "topo sort result :\n";
for (int i = 0; i < n; i++)
{
cout <<aov.g[aov.topo[i]].val <<' ';
}
cout<<endl;
}
输入例子
/*
6 8
A B C D E F
A B
A C
A D
C B
C E
D E
F E
F D
*/
输出结果
topo sort result :
A F C D B E