考研复试系列——第八节 拓扑排序

考研复试系列——第八节 拓扑排序

前言

拓扑排序最适于解决判断一个有向图是不是有向无环图的问题。在考研机试中也是经常出现的,但是题目又各不相同,只要抓住问题的根本, 即拓扑排序判断有向无环图的本质就可以以不变应万变。本节依然和前面依然,侧重于说明算法的编程实现。

拓扑排序——Kahn

看了网上其他的资料大多是以图的变化讲解拓扑排序,并没有说明算法实现的过程,所以下面以表格的形式来说明算法的过程以及如何把表格的 转换过程实现为具体的算法。

《考研复试系列——第八节 拓扑排序》

给出这样一个图,我们知道它的拓扑排序序列是1 2 3 4 或者 1 3 2 4 。但是在算法实现中具体该如何实现这个过程呢? 我们先使用自然语言藐视整个过程。首先建立这样一个表格:
《考研复试系列——第八节 拓扑排序》

开始时节点的入度初始化为0,后继节点也是空。 现在假设输入一条边 1—>2  (边的先后输入顺序不影响的),OK 开始更新这个表格,输入边是1到2,所以2的入度加1,1的后继节点加入节点2,此时表格如下:  
《考研复试系列——第八节 拓扑排序》

然后依次其他的边,最终表格如下:
《考研复试系列——第八节 拓扑排序》

然后我们就开始基于这个表格进行处理。然后我们扫描一遍入度,如果入度为0,说明对应节点没有前驱,那就把它加入到一个队列中(其实用栈什么的都可以):

《考研复试系列——第八节 拓扑排序》

OK,接下来取队列中的队头元素,也就是节点1 ,并将其出队列,然后查表它的后继节点是2和3 ,于是将2和3的入度都减去1 ,并判断节点2和3的入度是否是0,若是0则加入队列(显然因为节点2和3的入度发生了改变,所以我们只需要判断节点2和3的入度就可以了)此时表格以及队列为:

《考研复试系列——第八节 拓扑排序》

然后采取和前面一样的策略,从队列中弹出队头元素即节点2 ,查表其后继为节点4,将节点4的入度减去1,判断是否为0,不为0不做操作,继续从队列中取出 节点3,查表其后继为节点4,将节点4的入度减去1,判断是否为0,这是4的入度为0了,于是将节点4加入队列。 然后从队列中取队头元素即节点4,查表没有后继了,然后发现队列是为空了,于是算法结束。

下面我们来编程实现:思考一下,入度我们可以使用一个数组来记录,后继节点我们可以使用链表,为了方便我们使用vector数组来替代链表。队列直接使用 STL中的queue就好了。

#include<iostream>
#include<vector>
#include<queue>
#include<string>
using namespace std;

vector<int> next[101];//保存某节点的后继
queue<int> Q;//队列
int inNode[101];//记录节点的入度

int main()
{
	int n,m;//n个顶点,m条边
	while(cin>>n>>m && n && m)
	{
		int i;
		for(i=1;i<=n;i++)//下标从1开始
		{
			inNode[i] = 0;//初始化
			next[i].clear();//清空
		}
		while(!Q.empty())//清空
			Q.pop();
		for(i=1;i<=m;i++)//输入边信息
		{
			int a,b;
			cin>>a>>b;
			inNode[b]++;
			next[a].push_back(b);
		}
		int cnt = 0;//用于累加已经确定拓扑序列的结点个数
		for(i=1;i<=n;i++)//将入度为0的节点加入队列
		{
			if(inNode[i] == 0)
				Q.push(i);
		}
		while(!Q.empty())//队列非空则重复执行
		{
			//取队头节点并弹出
			int now = Q.front();
			Q.pop();
			cnt++;//确定一个节点总数加1
			for(i=0;i<next[now].size();i++)//遍历处理后继
			{
				inNode[next[now][i]]--;//入度减1
				if(inNode[next[now][i]] == 0)//若节点入度变为0
				{
					Q.push(next[now][i]);//将其加入队列
				}
			}

		}
		if(cnt == n)
			cout<<"这是一个有向无环图!"<<endl;
		else
			cout<<"这不是一个有向无环图!"<<endl;
	}
	return 0;
}

    原文作者:拓扑排序
    原文地址: https://blog.csdn.net/cassiePython/article/details/60738441
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞