图的应用之拓扑排序实现(辅助栈)

何为拓扑排序:

一般常见的图是有环的,不需要考虑顶点的先后顺序,而比如在一些工程中,工程的流程图就需要考虑顶点的先后顺序,比如B的前置条件是完成A,这就需要拓扑排序来判断图是否满足拓扑次序,并且能够形象的显示各个顶点的先后顺序。

拓扑排序有多种解,拓扑排序的解并不是唯一的,有些顶点的优先性是相同的。

通常我们把顶点表示活动,边表示活动的先后关系的有向图称为顶点活动网(Activity On Vertex Network),即AOV网。

拓扑排序的算法思路:

有向图的每个顶点有不同的入度,不断把入度为0的顶点的去除,并去除与之相连的边,把其相连顶点的入度减小1,不断循环。

最终判断是否输出的顶点数小于原图的顶点数,小于则不满足拓扑次序,否则满足拓扑次序,输出的顶点为一种拓扑序列。

拓扑排序所需的图的邻接表结构:

为了方便去除入度为0的顶点和边,所以使用带入度的图的邻接结构,图的邻接表结构如下:

#define MAXVERTEX 10       //最大顶点数,默认为10
struct EdgeNode          //边表
{
	int adjvertex;       //邻接点的下标
	int weight;          //权值
	EdgeNode *next;     //指针指向下一个邻接点
};

typedef struct VertexNode      //顶点表
{
	int data;            //顶点信息
	int in;               //顶点入度
	EdgeNode *firstEdge;       //边表指针,指向边表
}AdjList[MAXVERTEX];

typedef struct GraphAdjList
{
	AdjList adjList;
	int vertexesNum;        //顶点数
	int edgesNum;           //边数
}*GraphAdjList;

拓扑排序实现:

辅助建立了一个栈来输出入度为0的顶点

//拓扑排序
bool TopologicalSort(GraphAdjList GAL)
{
	int i;//用于循环
	int count;            //存储要输出的顶点个数
	EdgeNode *e;
	int k;    
	//初始化用于辅助的栈
	stack<int> stack;     //栈用于存放入度为0的顶点
	int topNum = 0;            //存储取出的栈顶数
	//将入度为0的顶点放入栈
	for (i = 0; i < GAL->vertexesNum; i++)
	{
		if (GAL->adjList[i].in == 0)
		{
			stack.push(i);
		}
	}
	while (stack.empty() != true)     //如果存在入度为0的顶点,不断循环
	{
		topNum = stack.top();  //topNum赋值为栈顶指针
		stack.pop();       //栈顶出栈
		count++;          //输出个数自增1
		cout << GAL->adjList[topNum].data << endl;  //输出顶点
		//遍历该顶点的邻接表
		for (e = GAL->adjList[topNum].firstEdge; e; e = e->next)
		{
			k = e->adjvertex;
			if ((--GAL->adjList[k].in) == 0) //邻接点自减1,并判断是否为0
			{
				stack.push(k);
			}
		}
	}
	//循环结束,判断是否是拓扑次序
	if (count<GAL->vertexesNum)
	{
		return false;
	}
	else
	{
		return true;
	}
}

拓扑排序时间复杂度:

初始遍历入度为0的顶点复杂度为O(n),后来循环中入栈出栈,复杂度为O(e),总的时间复杂度O(n+e)。

  • 0
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值