数据结构随笔——图的拓扑排序及关键路径

一、拓扑排序

由AOV网构造拓扑序列的拓扑排序算法主要是循环执行以下两步,直到不存在入度为0的顶点为止。

  1. 选择一个入度为0的顶点并输出之。
  2. 从网中删除此顶点及所有出边。

循环结束后,若输出的顶点数小于网中的顶点数,则输出“有回路”信息,否则输出的顶点序列就是一种拓扑序列。

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

#define MAXVEX 100
using namespace std;
typedef struct edge_node //边表节点
{
	int adjvex;//邻接点域
	int weight;//权值
	struct edge_node* next;
}edge_node;
typedef struct vertex_node //顶点表节点
{
	int in;//入度
	int data;//顶点信息
	edge_node* first_edge;
}vertex_node,AdjList[MAXVEX];
typedef struct
{
	AdjList adjlist;
	int num_vertexes, num_edges;
}graphadjlist;
bool TopologicalSort(graphadjlist* G)
{
	edge_node* e;
	int top = 0;//栈下标
	int count = 0;//记数输出顶点个数
	int stack[MAXVEX];//建栈储存入度0的点
	int get_top;//出栈元素
	for (int i = 0; i < G->num_vertexes; i++)
	{
		if (G->adjlist[i].in == 0)
			stack[++top] = i;
	}
	while (top != 0)
	{
		get_top = stack[top--];
		cout << G->adjlist[get_top].data;//打印顶点
		count++;
		int k;
		for (e = G->adjlist[get_top].first_edge;; e = e->next)
		{
			k = e->adjvex;
			G->adjlist[k].in--;//该点邻接点域入度减一
			if (G->adjlist[k].in == 0)
				stack[++top] = k;
		}
	}
	if (count < G->num_vertexes)//小于顶点数,存在环
		return false;
	else
		return true;
}

二、关键路径

在这里插入图片描述
只有在某顶点所代表的事件发生后,从该顶点出发的各有向边所代表的活动才能开始。只有在进入某一顶点的各有向边所代表的活动都已经结束,该顶点所代表的事件才能发生。表示实际工程计划的AOE网应该是无环的,并且存在唯一的入度为0的开始顶点和唯一的出度为0的完成顶点。

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述

当网中关键路径不唯一时,只有加快的关键活动或关键活动组合包括在所有的关键路径上才能缩短工期。

int etv[MAXVEX];//事件最早发生数组
int ltv[MAXVEX];//事件最迟发生数组
int stack2[MAXVEX];
int top2 = 0;//操作栈2

bool TopologicalSort(graphadjlist* G)
{
	edge_node* e;
	int top = 0;//栈下标
	int count = 0;//记数输出顶点个数
	int stack[MAXVEX];//建栈储存入度0的点
	int get_top;//出栈元素
	for (int i = 0; i < G->num_vertexes; i++)
	{
		if (G->adjlist[i].in == 0)
			stack[++top] = i;
	}
	for (int i = 0; i < G->num_vertexes; i++)
		etv[i] = 0;
	while (top != 0)
	{
		get_top = stack[top--];
		cout << G->adjlist[get_top].data;//打印顶点
		stack2[++top2] = get_top;
		count++;
		int k;
		for (e = G->adjlist[get_top].first_edge;; e = e->next)
		{
			k = e->adjvex;
			G->adjlist[k].in--;//该点邻接点域入度减一
			if (G->adjlist[k].in == 0)
				stack[++top] = k;
			if (etv[get_top ] + e->weight > etv[k])
			//求各顶点最早发生时间
				etv[k] = etv[get_top] + e->weight;//更新后面

		}
	}
	if (count < G->num_vertexes)//小于顶点数,存在环
		return false;
	else
		return true;
}
//求关键路径
void CriticalPath(graphadjlist* G)
{
	edge_node* e;
	int ete, lte;//活动最早和最迟发生时间
	int get_top,k;
	TopologicalSort(G);
	for (int i = 0; i < G->num_vertexes; i++)
	{
		ltv[i] = etv[G->num_vertexes - 1];//初始化事件的最迟发生时间
	}
	while (top2)
	{
		get_top = stack2[top2--];//将拓扑排序出栈
		for (e = G->adjlist[get_top].first_edge;; e = e->next)
		{
			k = e->adjvex;
			if (ltv[k] - e->weight > ltv[get_top])
				etv[get_top] = ltv[k] - e->weight;//倒退更新前面
		}
	}
	for (int j = 0; j < G->num_vertexes; j++)
	{
		for (e = G->adjlist[j].first_edge;; e = e->next)
		{
			k = e->adjvex;
			lte = ltv[k] - e->weight;//最迟为事件最迟时减去活动时间
			ete = etv[k];//最早为事件开始
			if (lte == ete)
				printf("<V %d ,V %d>,权值%d", G->adjlist[j].data, G->adjlist[k].data, e->weight);
		}
	}
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值