拓扑排序的实现_TopoSort

拓扑排序是求一个AOV网(顶点代表活动, 各条边表示活动之间的率先关系的有向图)中各活动的一个拓扑序列的运算, 可用于測试AOV

网络的可行性.

整个算法包含三步:

1.计算每一个顶点的入度, 存入InDegree数组中.

2.检查InDegree数组中顶点的入度, 将入度为零的顶点进栈.

3.不断从栈中弹出入度为0的顶点并输出, 并将该顶点为尾的全部邻接点的入度减1, 若此时某个邻接点的入度为0, 便领其进栈. 反复步骤

3, 直到栈为空时为止. 此时, 或者所有顶点都已列出, 或者因图中包括有向回路, 顶点未能所有列出.

实现代码:

#include "iostream"
#include "cstdio"
#include "cstring"
#include "algorithm"
#include "queue"
#include "stack"
#include "cmath"
#include "utility"
#include "map"
#include "set"
#include "vector"
#include "list"
#include "string"
using namespace std;
typedef long long ll;
const int MOD = 1e9 + 7;
const int INF = 0x3f3f3f3f;
enum ResultCode { Underflow, Overflow, Success, Duplicate, NotPresent, Failure, HasCycle };
template <class T>
struct ENode
{
	ENode() { nxtArc = NULL; }
	ENode(int vertex, T weight, ENode *nxt) {
		adjVex = vertex;
		w = weight;
		nxtArc = nxt;
	}
	int adjVex;
	T w;
	ENode *nxtArc;
	/* data */
};
template <class T>
class Graph
{
public:
	virtual ~Graph() {}
	virtual ResultCode Insert(int u, int v, T &w) = 0;
	virtual ResultCode Remove(int u, int v) = 0;
	virtual bool Exist(int u, int v) const = 0;
	/* data */
};
template <class T>
class LGraph: public Graph<T>
{
public:
	LGraph(int mSize);
	~LGraph();
	ResultCode Insert(int u, int v, T &w);
	ResultCode Remove(int u, int v);
	bool Exist(int u, int v) const;
	int Vertices() const { return n; }
	void Output();
protected:
	ENode<T> **a;
	int n, e;
	/* data */
};
template <class T>
void LGraph<T>::Output()
{
	ENode<T> *q;
	for(int i = 0; i < n; ++i) {
		q = a[i];
		while(q) {
			cout << '(' << i << ' ' << q -> adjVex << ' ' << q -> w << ')';
			q = q -> nxtArc;
		}
		cout << endl;
	}
	cout << endl << endl;
}
template <class T>
LGraph<T>::LGraph(int mSize)
{
	n = mSize;
	e = 0;
	a = new ENode<T>*[n];
	for(int i = 0; i < n; ++i)
		a[i] = NULL;
}
template <class T>
LGraph<T>::~LGraph()
{
	ENode<T> *p, *q;
	for(int i = 0; i < n; ++i) {
		p = a[i];
		q = p;
		while(p) {
			p = p -> nxtArc;
			delete q;
			q = p;
		}
	}
	delete []a;
}
template <class T>
bool LGraph<T>::Exist(int u, int v) const
{
	if(u < 0 || v < 0 || u > n - 1 || v > n - 1 || u == v) return false;
	ENode<T> *p = a[u];
	while(p && p -> adjVex != v) p = p -> nxtArc;
	if(!p) return false;
	return true;
}
template <class T>
ResultCode LGraph<T>::Insert(int u, int v, T &w)
{
	if(u < 0 || v < 0 || u > n - 1 || v > n - 1 || u == v) return Failure;
	if(Exist(u, v)) return Duplicate;
	ENode<T> *p = new ENode<T>(v, w, a[u]);
	a[u] = p;
	e++;
	return Success;
}
template <class T>
ResultCode LGraph<T>::Remove(int u, int v)
{
	if(u < 0 || v < 0 || u > n - 1 || v > n - 1 || u == v) return Failure;
	ENode<T> *p = a[u], *q = NULL;
	while(p && p -> adjVex != v) {
		q = p;
		p = p -> nxtArc;
	}
	if(!p) return NotPresent;
	if(q) q -> nxtArc = p -> nxtArc;
	else a[u] = p -> nxtArc;
	delete p;
	e--;
	return Success;
}
template <class T>
class ExtLgraph: public LGraph<T>
{
public:
	ExtLgraph(int mSize): LGraph<T>(mSize) {}
	void TopoSort(int *order);
private:
	void CallInDegree(int *InDegree);
	/* data */
};
template <class T>
void ExtLgraph<T>::TopoSort(int *order)
{
	int *InDegree = new int[LGraph<T>::n];
	int top = -1; // 置栈顶指针为-1, 代表空栈
	ENode<T> *p;
	CallInDegree(InDegree); // 计算每一个顶点的入度
	for(int i = 0; i < LGraph<T>::n; ++i)
		if(!InDegree[i]) { // 图中入度为零的顶点进栈
			InDegree[i] = top;
			top = i;
		}
	for(int i = 0; i < LGraph<T>::n; ++i) { // 生成拓扑排序
		if(top == -1) throw HasCycle; // 若堆栈为空, 说明图中存在有向环
		else {
			int j = top;
			top = InDegree[top]; // 入度为0的顶点出栈
			order[i] = j;
			cout << j << ' ';
			for(p = LGraph<T>::a[j]; p; p = p -> nxtArc) { // 检查以顶点j为尾的全部邻接点
				int k = p -> adjVex; // 将j的出邻接点入度减1
				InDegree[k]--;
				if(!InDegree[k]) { // 顶点k入度为0时进栈
					InDegree[k] = top;
					top = k;
				}
			}
		}
	}
}
template <class T>
void ExtLgraph<T>::CallInDegree(int *InDegree)
{
	for(int i = 0; i < LGraph<T>::n; ++i)
		InDegree[i] = 0; // 初始化InDegree数组
	for(int i = 0; i < LGraph<T>::n; ++i)
		for(ENode<T> *p = LGraph<T>::a[i]; p; p = p -> nxtArc) // 检查以顶点i为尾的全部邻接点
			InDegree[p -> adjVex]++; // 将顶点i的邻接点p -> adjVex的入度加1
}
int main(int argc, char const *argv[])
{
	ExtLgraph<int> lg(9);
	int w = 10; lg.Insert(0, 2, w); lg.Insert(0, 7, w);
	lg.Insert(2, 3, w); lg.Insert(3, 5, w);
	lg.Insert(3, 6, w); lg.Insert(4, 5, w);
	lg.Insert(7, 8, w); lg.Insert(8, 6, w);
	int *order = new int[9];
	lg.TopoSort(order);
	cout << endl;
	delete []order;
	return 0;
}
时间: 2024-08-25 14:24:07

拓扑排序的实现_TopoSort的相关文章

拓扑排序讲解

在这里我们要说的拓扑排序是有前提的 我们在这里说的拓扑排序是基于有向无环图的!!!. (⊙o⊙)…我所说的有向无环图都知道是什么东西吧.. 如果不知道,我们下面先来来说说什么是有向无环图. 所谓有向无环图,顾名思义是不存在环的有向图(至于有向图是什么不知道的在前面我们有一个图论讲解上都有). 点的入度:以这个点为结束点的边数. 点的出度:以这个点为出发点的边的条数. 拓扑序就是对于一个节点的一个排列,使得(u,v)属于E,那么u一定出现在v的前面.然而拓扑排序就是一个用来求拓扑序的东西. 对于左

CSU 1804: 有向无环图(拓扑排序)

http://acm.csu.edu.cn/csuoj/problemset/problem?pid=1804 题意:…… 思路:对于某条路径,在遍历到某个点的时候,之前遍历过的点都可以到达它,因此在这个时候对答案的贡献就是∑(a1 + a2 + a3 + ... + ai) * bv,其中a是之前遍历到的点,v是当前遍历的点. 这样想之后就很简单了.类似于前缀和,每次遍历到一个v点,就把a[u]加给a[v],然后像平时的拓扑排序做就行了. 1 #include <bits/stdc++.h>

7-9-有向图无环拓扑排序-图-第7章-《数据结构》课本源码-严蔚敏吴伟民版

课本源码部分 第7章  图 - 有向无环图拓扑排序 ——<数据结构>-严蔚敏.吴伟民版        源码使用说明  链接??? <数据结构-C语言版>(严蔚敏,吴伟民版)课本源码+习题集解析使用说明        课本源码合辑  链接??? <数据结构>课本源码合辑        习题集全解析  链接??? <数据结构题集>习题解析合辑        本源码引入的文件  链接? Status.h.SequenceStack.c.ALGraph.c    

hihoCoder 1175:拓扑排序二

题目链接: http://hihocoder.com/problemset/problem/1175 题目难度:一星级(简单题) 今天闲来无事,决定刷一道水题.结果发现这道水题居然把我卡了将近一个钟头. 最后终于调通了.总结起来,原因只有一个:不够仔细. 思路不用细说了,就是拓扑排序的简单应用.然而,一些不起眼的细节才是让你掉坑里的真正原因. 猜猜哪儿可能出bug? // A simple problem, but you can't be too careful with it. #inclu

hdu1285(拓扑排序)

这道题要求没有输赢关系的两个元素必须按照升序输出,有输赢关系的,赢得在输的前面,所以用队列或者栈来降低时间复杂度的优化过的拓扑排序会出错. 比如这组输入 5 3 1 2 2 3 4 5 至少我写的两种拓扑排序都wa了.但是不用队列或者栈来优化的话, 1.每次都从头至尾扫描一遍,找到一个没标记过的节点, 2.将它标记 3.然后删除从它出来的每条边. 重复这三个操作,加标记的次序,就是题目要的答案. 下面的代码中用到了队列,但只是用来保存答案而已.并没有用它优化的意思. #include <iost

uva 10305 Ordering Tasks(拓扑排序)

拓扑排序,不用判断是否有环,dfs挺简单的 代码: #include<stdio.h> #include<string.h> #include<stdlib.h> int map[105][105]; int visit[105]; int c[105]; int n,m,t; void dfs(int x) { visit[x] = 1; for(int i=1; i<=n; i++) { if(!visit[i]&&map[i][x]==1)

NOJ 2015年陕西省程序设计竞赛网络预赛(正式赛)(忙碌的选课系统-拓扑排序注意重边)

D - 忙碌的选课系统 Time Limit: 10000 ms        Memory Limit: 65536 KB Submit Description 每学期末,都是万众瞩目的选课时间,由于人数过多,某学校的服务器常常被无数的学生挤的爆掉,这是,教务系统大人说,你们选个课都这么慢,居然还怪我们.于是,每次教务系统都会在服务器快要瘫痪前关闭它.在无数学生的强烈抗议下,教务系统妥协了,再给每个人一次机会,但他让我们用最快的方式决定该选的课程,选上后就退出. 这让大一学渣狗犯了难,在新的选

POJ1420 Spreadsheet(拓扑排序)注意的是超内存

Spreadsheet Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 617   Accepted: 290 Description In 1979, Dan Bricklin and Bob Frankston wrote VisiCalc, the first spreadsheet application. It became a huge success and, at that time, was the ki

拓扑排序之变量序列算法分析

拓扑排序之变量序列 巧若拙(欢迎转载,但请注明出处:http://blog.csdn.net/qiaoruozhuo) 题目描述: 假设有n个变量(1<=n<=26,变量名用单个小写字母表示),还有m个二元组(u,v),分别表示变量u小于v.那么,所有变量从小到大排列起来应该是什么样子的呢? 例如有4个变量a,b,c,d,若以知a<b,c<b,d<c,则这4个变量的排序可能是a<d<c<b.尽管还有可能其他的可能,你只需找出其中的一个即可. 输入: 输入为一