拓扑排序算法C++实现

欢迎扫码关注微信公众号
在这里插入图片描述

拓扑排序算法,基本思想:

	1、从有向图中选取一个没有前驱(入度为0)的顶点,并输出之
	2、从有向图中删去此顶点以及所有以它为尾的弧
	3、重复上述两步,直至图空,或者图不空但找不到无前驱的顶点为止

数据结构PPT图论在第七章:http://download.csdn.net/download/include_heqile/10188767

使用邻接表和一个用来存储入度为0的节点的栈实现

在算法中需要用定量的描述替代定性的概念
	没有前驱的顶点   <==> 入度为零的顶点
	删除顶点及以它为尾的弧  <==>  弧头顶点的入度减1
	
为实现拓扑排序,采用邻接表作为有向图的存储结构,并增设一个入度数组indegree[ ]

为了避免每一次选入度为0的顶点时重复扫描入度数组,可以利用栈来存储入度为0的顶点
代码:有详细注释
#include<stdio.h>
#include<stdlib.h>

#define m 100
#define n 6
#define e 8

typedef struct node1 {
	int info;
	int adjvertex;//这个域就是本节点在数组中的位置
	struct node1 *nextarc;
} glinklistnode;//这个是在后面邻接的节点

typedef struct node2 {
	int vertexinfo;
	glinklistnode *firstarc;
} glinkheadnode;//邻接表的数组,vertexinfo存的是每个点的入度
//数组中的节点比邻接表中的节点多了一个vertexinfo域,用来存储入度值

//创建邻接链表
void createAdjlist(glinkheadnode g[]) {
	int i,j,k;
	glinklistnode *p;
	for(i=0; i<n; i++) {
		g[i].vertexinfo=i;
		g[i].firstarc=0;
	}//初始化每个节点在数组中的位置
	for(k=0; k<e; k++) {
		scanf("%d%d",&i,&j);//输入两个关联节点
		p=(glinklistnode *)malloc(sizeof(glinklistnode));
		p->adjvertex=j;
		p->nextarc=g[i].firstarc;//使用的插入方式建立,后来的更接近根节点
		g[i].firstarc=p;//第一个邻接点是p
		 
	}
}

//拓扑排序函数
void toposort(glinkheadnode g[]) {
	int i,v,w,sum=0, indegree[n];
	struct {
		int s[n];
		int top;
	} stack;//建立一个栈,栈中的s数组用来存入度为0的节点
	glinklistnode *p;
	for (i=0; i<n; i++) indegree[i]=0;//初始化indegree数组,完全可以使用memset
	for (i=0; i<n; i++)
		for(p=g[i].firstarc; p!=0; p=p->nextarc) //这一层for循环用来统计
			indegree[p->adjvertex]++;//经过两个for循环,即可把所有节点的入度算统计出来
	for(i=0,stack.top= -1; i<n; i++) if(indegree[i]==0) {
			stack.top++;
			stack.s[stack.top]=i;
		}//这个for循环用来入栈入度为0的节点
	while(stack.top!= -1) {
		printf("%d\t",stack.s[stack.top]);
		sum=sum+1;
		v=stack.s[stack.top];
		stack.top=stack.top-1;//出栈top
		p=g[v].firstarc;//读取该节点的第一个邻接点
		while (p!=0) {//遍历p的所有邻接点
			w=p->adjvertex;
			indegree[w]=indegree[w]-1;//因为前导节点会被删掉,因此它的入度值需要-1
			if (indegree[w]==0) {//如果它的入度等于0,就将这个节点也入栈
				stack.top=stack.top+1;
				stack.s[stack.top]=w;
			}
			p=p->nextarc;//往下走
		}
	}
	if(sum<n) printf("The AOV network has a cycle\n");//如果最后输出的节点个数少于总结点数,说明图中有回路
}

int main() {
	glinkheadnode g[m];
	createAdjlist(g);
	toposort(g);
	return 0;
}
  • 1
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值