[手撕数据结构] 拓扑排序与关键路径

拓扑排序

代码如下

有了逆邻接表的话求入度比较舒服

#include<iostream>
#include<stdlib.h>
using namespace std;
#define MVNum 100      //最大顶点数

typedef struct ArcNode
{
	int adjvex;//该边所指向的顶点的位置
	struct ArcNode* next;
}ArcNode;//边结点

typedef struct VNode
{
	char data;//该边所指向的顶点的位置
	ArcNode* firstarc;
}VNode;//顶点 

typedef struct
{
	VNode vertices[MVNum];     //邻接表
	VNode fvertices[MVNum];    //逆邻接表
	int vexnum;                //图的当前顶点数
	int arcnum;                //图的当前边数
}ALGraph;//Adjacency List Graph
int LocateVex(ALGraph* G, char v)//找到结点V在图G中的位置 即下标
{
	for (int i = 0; i < G->vexnum; i++)
	{
		if (G->vertices[i].data == v)
			return i;
	}
	cout << "没找到" << endl;
	return 0;
}

void CreatALG(ALGraph* G)//邻接表表示法创建有向图
{
	cout << "请输入图的总顶点数与总边数: ";
	cin >> G->vexnum >> G->arcnum;//输入总顶点数 总边数
	cout << "输入顶点信息: ";
	for (int i = 0; i < G->vexnum; i++)//初始化
	{
		cin >> G->vertices[i].data;
		G->vertices[i].firstarc = NULL;
		G->fvertices[i].data= G->vertices[i].data;
		G->fvertices[i].firstarc = NULL;
	}
	cout << "输入相连的结点" << endl;
	char v1, v2;
	for (int k = 0; k < G->arcnum; k++)//构造邻接表与逆邻接表
	{
		cin >> v1 >> v2;                      //v1-->v2
		int i = LocateVex(G, v1);
		int j = LocateVex(G, v2);

		ArcNode* p1 = new ArcNode;
		p1->adjvex = j;                       //邻接点序号
		p1->next = G->vertices[i].firstarc;
		G->vertices[i].firstarc = p1;         //前插
		ArcNode* p2 = new ArcNode;            
		p2->adjvex = i;
		p2->next = G->fvertices[j].firstarc;
		G->fvertices[j].firstarc = p2;
	}
	cout << "邻接表如下" << endl;
	for (int i = 0; i < G->vexnum; i++)
	{
		cout << G->vertices[i].data << "->";
		ArcNode* p = G->vertices[i].firstarc;
		while (p != NULL)
		{
			cout << G->vertices[p->adjvex].data << "->";
			p = p->next;
		}
		cout << "->NULL" << endl;
	}
	cout << "逆邻接表如下" << endl;
	for (int i = 0; i < G->vexnum; i++)
	{
		cout << G->fvertices[i].data << "->";
		ArcNode* p = G->fvertices[i].firstarc;
		while (p != NULL)
		{
			cout << G->fvertices[p->adjvex].data << "->";
			p = p->next;
		}
		cout << "->NULL" << endl;
	}
}
int indegree[MVNum];//存储入度数组
void FindInDegree(ALGraph G, int indegree[]) //获取入度
{
	for (int i = 0; i < G.vexnum; i++) 
	{
		int cnt = 0;
		while (G.fvertices[i].firstarc != NULL)
		{
			cnt++;
			G.fvertices[i].firstarc = G.fvertices[i].firstarc->next;
		}
		indegree[i] = cnt;
	}
}
int topo[MVNum];
int stack[MVNum];//辅助栈
int top = 0;
void TopologicalSort(ALGraph *G, int* topo)
{
     FindInDegree(*G, indegree);
	 for (int i = 0; i < G->vexnum; i++)
	 {
		 if (indegree[i] == 0)
			 stack[top++] = i;
	 }
	 int m = 0;
	 while(top>=0)
	 {
		 int i = stack[--top];
		 topo[m++] = i;
		 ArcNode* p = G->vertices[i].firstarc;
		 while (p != NULL)
		 {
			 int k = p->adjvex;
			 indegree[k]--;
			 if (indegree[k] == 0)
			 {
				 stack[top++] = k;
			 }
			 p = p->next;
		 }
	 }
	 if (m < G->vexnum)
	 {
		 cout << "该图有回路" << endl;
	 }
	 else
	 {
		 cout << "拓扑序列如下" << endl;
		 for (int i = 0; i < G->vexnum; i++)
		 {
			 cout << G->vertices[topo[i]].data << "  ";
		 }
	 }
	 return;
}
int main()
{
	ALGraph* G = new ALGraph;
	CreatALG(G);
	TopologicalSort(G, topo);
}

按照下图进行测试

 

 结果如下

 关键路径

代码如下

#include<iostream>
#include<stdlib.h>
using namespace std;
#define MVNum 100      //最大顶点数

typedef struct ArcNode
{
	int adjvex;//该边所指向的顶点的位置
	int weight;
	struct ArcNode* next;
}ArcNode;//边结点

typedef struct VNode
{
	char data;//该边所指向的顶点的位置
	int weight;
	ArcNode* firstarc;
}VNode;//顶点 

typedef struct
{
	VNode vertices[MVNum];     //邻接表
	VNode fvertices[MVNum];    //逆邻接表
	int vexnum;                //图的当前顶点数
	int arcnum;                //图的当前边数
}ALGraph;//Adjacency List Graph
int LocateVex(ALGraph* G, char v)//找到结点V在图G中的位置 即下标
{
	for (int i = 0; i < G->vexnum; i++)
	{
		if (G->vertices[i].data == v)
			return i;
	}
	cout << "没找到" << endl;
	return 0;
}

void CreatALG(ALGraph* G)//邻接表表示法创建有向网
{
	cout << "请输入图的总顶点数与总边数: ";
	cin >> G->vexnum >> G->arcnum;//输入总顶点数 总边数
	cout << "输入顶点信息: ";
	for (int i = 0; i < G->vexnum; i++)//初始化
	{
		cin >> G->vertices[i].data;
		G->vertices[i].firstarc = NULL;
		G->fvertices[i].data = G->vertices[i].data;
		G->fvertices[i].firstarc = NULL;
	}
	cout << "输入相连的结点与权值" << endl;
	char v1, v2;
	int weight;
	for (int k = 0; k < G->arcnum; k++)//构造邻接表与逆邻接表
	{
		cin >> v1 >> v2 >> weight;                      //v1-->v2
		int i = LocateVex(G, v1);
		int j = LocateVex(G, v2);

		ArcNode* p1 = new ArcNode;
		p1->weight = weight;
		p1->adjvex = j;                       //邻接点序号
		p1->next = G->vertices[i].firstarc;
		G->vertices[i].firstarc = p1;         //前插
		ArcNode* p2 = new ArcNode;
		p2->adjvex = i;
		p2->next = G->fvertices[j].firstarc;
		G->fvertices[j].firstarc = p2;
	}
	cout << "邻接表如下" << endl;
	for (int i = 0; i < G->vexnum; i++)
	{
		cout << G->vertices[i].data << "->";
		ArcNode* p = G->vertices[i].firstarc;
		while (p != NULL)
		{
			cout << G->vertices[p->adjvex].data << "->";
			p = p->next;
		}
		cout << "NULL" << endl;
	}
	cout << "逆邻接表如下" << endl;
	for (int i = 0; i < G->vexnum; i++)
	{
		cout << G->fvertices[i].data << "->";
		ArcNode* p = G->fvertices[i].firstarc;
		while (p != NULL)
		{
			cout << G->fvertices[p->adjvex].data << "->";
			p = p->next;
		}
		cout << "NULL" << endl;
	}
}
int indegree[MVNum];//存储入度数组
void FindInDegree(ALGraph G, int indegree[])
{
	for (int i = 0; i < G.vexnum; i++)
	{
		int cnt = 0;
		while (G.fvertices[i].firstarc != NULL)
		{
			cnt++;
			G.fvertices[i].firstarc = G.fvertices[i].firstarc->next;
		}
		indegree[i] = cnt;
	}
}

int topo[MVNum];
int stack[MVNum];//辅助栈
int top = 0;

void TopologicalSort(ALGraph* G, int* topo)
{
	FindInDegree(*G, indegree);
	for (int i = 0; i < G->vexnum; i++)
	{
		if (indegree[i] == 0)
			stack[top++] = i;
	}
	int m = 0;
	while (top >= 0)
	{
		int i = stack[--top];
		topo[m++] = i;
		ArcNode* p = G->vertices[i].firstarc;
		while (p != NULL)
		{
			int k = p->adjvex;
			indegree[k]--;
			if (indegree[k] == 0)
			{
				stack[top++] = k;
			}
			p = p->next;
		}
	}
	if (m < G->vexnum)
	{
		cout << "该图有回路" << endl;
	}
	else
	{
		cout << "拓扑序列如下" << endl;
		for (int i = 0; i < G->vexnum; i++)
		{
			cout << G->vertices[topo[i]].data << "  ";
		}
	}
	cout << endl;
	return;
}
int ve[MVNum], vl[MVNum];
void CriticalPath(ALGraph* G) //关键路径
{
	TopologicalSort(G, topo);
	int n = G->vexnum;
	/*----------------------每个事件的最早发生时间-----------------------*/
	for (int i = 0; i < n; i++)
	{
		int k = topo[i];//取得拓扑排序中的顶点序号
		ArcNode* p = G->vertices[k].firstarc;
		while (p != NULL)
		{
			int j = p->adjvex;
			if (ve[j] < ve[k] + p->weight)
				ve[j] = ve[k] + p->weight;
			p = p->next;
		}
	}
	for (int i = 0; i < n; i++)
		vl[i] = ve[n - 1];        //为最迟开始时间赋初值
	/*----------------------每个事件的最迟发生时间-----------------------*/
	for (int i = n - 1; i >= 0; i--)
	{
		int k = topo[i];
		ArcNode* p = G->vertices[k].firstarc;
		while (p != NULL)
		{
			int j = p->adjvex;
			if (vl[k] > vl[j] - p->weight)
				vl[k] = vl[j] - p->weight;
			p = p->next;
		}
	}
	/*----------------------判断每一个活动是否为关键活动-----------------------*/
	int e = 0, l = 0;
	cout << "关键路径如下" << endl;
	for (int i = 0; i < n; i++)
	{
		ArcNode* p = G->vertices[i].firstarc;
		while (p != NULL)
		{
			int j = p->adjvex;
			e = ve[i];
			l = vl[j] - p->weight;
			if (e == l)
				cout << G->vertices[i].data << "--" << G->vertices[j].data << endl;
			p = p->next;
		}
	}
	return;
}
int main()
{
	ALGraph* G = new ALGraph;
	CreatALG(G);
	CriticalPath(G);
	return 0;
}

按照下图进行测试

 测试结果如下

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值