数据结构(C++)AOV网与拓扑排序

AOV网:在一个表示工程的有向图中,用顶点表示活动,用弧表示活动之间的优先关系,称这样的有向图为顶点表示活动的网,简称AOV网。

AOV网特点:
1.AOV网中的弧表示活动之间存在的某种制约关系。
2.AOV网中不能出现回路。

拓扑序列:
设G = (V,E)是一个具有n个顶点的有向图,V中的顶点序列v1, v2, …, vn称为一个拓扑序列,当且仅当满足下列条件:若从顶点vi到vj有一条路径,则在顶点的拓扑序列中顶点vi必在顶点vj之前。

**拓扑排序:**对一个有向图构造拓扑序列的过程称为拓扑排序 。

拓扑序列使得AOV网中所有应存在的前驱和后继关系都能得到满足。

基本思想:

⑴ 从AOV网中选择一个没有前驱的顶点并且输出;
⑵ 从AOV网中删去该顶点,并且删去所有以该顶点为尾的弧;
⑶ 重复上述两步,直到全部顶点都被输出,或AOV网中不存在没有前驱的顶点。

基本构造

根据图的链式存储结构建图,分别建立一条主链表,用来存储全部的顶点,每个顶点的数据分别有:
1、该顶点的前驱数量。
2、该顶点的顶点名称。
3、该顶点所指向的下一条的结构化边。

建立边表,其中边表的组成有该边的下一个顶点,还有在顶点表里原顶点所连接的其他顶点边。

struct ArcNode // 边
{
	int adjvex;
	ArcNode* next;
};
struct VertexNode // 顶点
{
	int pre;
	int vertex;
	ArcNode* firstedge;
};

构造函数

  1. 对于顶点表进行初始化,所有的前驱数量置0,定点名称直接标记下标号,指向第一条边为空。
  2. 输入边的起点和终点,设置一条边的,终点是b,使用头插法插入到a顶点的后方,并且b顶点的前驱数加1。
ALGraph(int n, int e)
{
	arcNum = e;
	vertexNum = n;
	ArcNode* s;
	for (int i = 1; i <= vertexNum; ++i)
	{
		adjlist[i].pre = 0;
		adjlist[i].vertex = i;
		adjlist[i].firstedge = NULL;
	}
	for (int i = 1; i <= arcNum; ++i)
	{
		int a, b;
		cin >> a >> b;
		s = new ArcNode;
		s->adjvex = b;
		s->next = adjlist[a].firstedge;
		adjlist[a].firstedge = s;
		adjlist[b].pre++;
	}
}

AOV求拓扑路径

  1. 首先,把所有前驱是0的顶点入栈,没有前驱结点可以直接入栈等待输出以及后续操作。
  2. 对于栈顶顶点,出栈,并且输出这个顶点的结点值,循环以该顶点开始的边表,找到后续的顶点并且前驱数量-1。
  3. 在栈不为空的条件下,循环进行第2步,直到栈为空,所有的顶点都遍历结束。
void AOV()
{
	stack<int>s;
	int j, k;
	ArcNode* p;
	for (int i = vertexNum; i >= 1; i--)
	{
		if (adjlist[i].pre == 0)
		{
			s.push(i);
		}
	}
	while (!s.empty())
	{
		j = s.top();
		s.pop();
		cout << "v" << adjlist[j].vertex << " ";
		p = adjlist[j].firstedge;
		while (p != NULL)
		{
			k = p->adjvex;
			adjlist[k].pre--;
			if (adjlist[k].pre == 0)
			{
				s.push(k);
			}
			p = p->next;
		}
	}
}

注:在入栈操作的时候利用了反向的压栈,因为有部分的题目要求在相同的条件下,尽可能地先输出结点值小的点,由于栈是先入后出的,所以反向压栈。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
拓扑排序是一种常用的有向无环图(DAG)的排序算法,其主要思想是将有向图中的节点按照一定的顺序进行排序,使得所有的有向边从排在前面的节点指向排在后面的节点。在AOV中,节点代表活动,有向边代表活动之间的先后关系。 以下是一个使用C语言实现拓扑排序的示例代码: ```c #include <stdio.h> #define MAXVEX 100 //节点最大数目 int main() { int i, j, k, n, e; int flag[MAXVEX]; int in[MAXVEX]; int topo[MAXVEX]; int arc[MAXVEX][MAXVEX]; //邻接矩阵 //输入节点数和边数 printf("请输入节点数和边数:"); scanf("%d%d", &n, &e); //初始化邻接矩阵和入度数组 for (i = 0; i < n; i++) { for (j = 0; j < n; j++) { arc[i][j] = 0; } in[i] = 0; flag[i] = 0; } //输入每条有向边的起始节点和结束节点 for (k = 0; k < e; k++) { printf("请输入第%d条有向边的起始节点和结束节点:", k + 1); scanf("%d%d", &i, &j); arc[i][j] = 1; in[j]++; } //拓扑排序 for (i = 0; i < n; i++) { if (in[i] == 0) { flag[i] = 1; topo[0] = i; break; } } for (i = 1; i < n; i++) { for (j = 0; j < n; j++) { if (flag[j] == 0 && in[j] == 0) { flag[j] = 1; topo[i] = j; for (k = 0; k < n; k++) { if (arc[j][k] == 1) { in[k]--; } } break; } } } //输出拓扑排序结果 printf("拓扑排序结果为:"); for (i = 0; i < n; i++) { printf("%d ", topo[i]); } printf("\n"); return 0; } ``` 在该代码中,使用邻接矩阵来表示有向图,使用入度数组来表示每个节点的入度。在拓扑排序过程中,依次遍历每个节点,如果该节点的入度为0,则将其加入到拓扑序列中,并将其后继节点的入度减1。重复这个过程直到所有节点都被遍历过。最终得到的拓扑序列就是一种满足所有先后关系的顺序。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值