【算法导论】邻接矩阵存储的拓扑排序

简介:         在很多应用中,很多事情都是按照一定的次序来进行的,比如说起床穿衣时,不可能先穿鞋再穿袜子,但是穿袜子和穿裤子可以不分先后次序。这种按照一定顺序进行的活动,可以使用顶点表示活动,顶点之间的有向边表示活动间的先后关系,这种有向无回路图说明了活动的先后次序。

        在很多应用中,很多事情都是按照一定的次序来进行的,比如说起床穿衣时,不可能先穿鞋再穿袜子,但是穿袜子和穿裤子可以不分先后次序。这种按照一定顺序进行的活动,可以使用顶点表示活动,顶点之间的有向边表示活动间的先后关系,这种有向无回路图说明了活动的先后次序。

        当活动只能单个进行时,如果可以将图中的所有顶点排列成一个线性序列vi1, vi2, …, vin,并且这个序列同时满足关系:若从顶点vi到顶点vj存在一条路径,则在线性序列中vi必在vj之前,我们就称这个线性序列为拓扑序列。把对有向无回路图构造拓扑序列的操作称为拓扑排序。

其基本思想:

        拓扑排序的基本操作为:

1.从图中选择一个入度为0的顶点并且输出它;

2.从图中删除此顶点及所有由它发出的边;

3.重复上述过程,直到图中没有入度为0的边。

以上的操作会产生两种结果:一种是图中的全部顶点都被输出,整个拓扑排序完成;另一种是图中顶点未被全部输出,剩余的顶点的入度均不为0,则说明网中存在有向环。

上述表述比较抽象,下面我用图解的方式来介绍其思想:

假设有向无回路图如下所示:

依次删除入度为0的顶点的过程如下:

         

                                    a)输出A                                              b)输出B            

               

                                    c)输出D                                             d)输出C 


                                                                              

                                    e)输出E                                            f)输出F


因此得到的拓扑排序序列为: A B D C E F G.

具体的程序实现如下:

#include<stdio.h>
#include<stdlib.h>
#define N 7//顶点个数

typedef struct 
{
	char vexs[N];//顶点数组
	int arcs[N][N];//邻接矩阵
}graph;

void TopoSort_matrix(graph g)
{
	int row[N]={0};//按照列来设置标志,为1表示已经输出(不再考虑),为0表示未输出。
	int v=1;//标志符,1表示已经输出(不再考虑),为0表示未输出,赋给row数组
	int i,j,k,t,m;
	for(k=0;k<N;k++)
	{
		for(j=0;j<N;j++)
		{
			if(row[j]==0)//活动j还未输出
			{
				t=1;//标识符
				for(i=0;i<N;i++)
					if(g.arcs[i][j]==1)//当前活动有入度(活动i必须在活动j之前)
					{
						t=0;
						break;
					}
				if(t==1)//活动j没有入度
				{
					m=j;
					break;
				}
			}
		}
		if(j!=N)
		{
			row[m]=v;
			printf("%c",g.vexs[m]);
			for(i=0;i<N;i++)
				g.arcs[m][i]=0;//将已经输出的活动所到达的下个活动的入度置为0
			v++;
		}
		else 
			break;
		}
		if(v-1<N)//当row中不是所有的元素都被赋予新值v时,说明有环存在
			printf("\n该有向图有环存在!");
	
}

void main()
{
	graph g;
	int matrix[N][N]={{0,1,1,0,0,0,0},
					  {0,0,0,0,0,1,1},
			    	  {0,0,0,0,0,0,1},
					  {0,0,1,0,1,0,0},
					  {0,0,0,0,0,0,1},
					  {0,0,0,0,0,0,0},
					  {0,0,0,0,0,0,0}};
	char vertex[N]={'A','B','C','D','E','F','G'};//初始化
		for(int i=0;i<N;i++)
		{
			g.vexs[i]=vertex[i];
			for(int j=0;j<N;j++)
				g.arcs[i][j]=matrix[i][j];
		}
	TopoSort_matrix(g);
	printf("\n");
}

注:如果程序出错,可能是使用的开发平台版本不同,请点击如下链接:  解释说明

原文:http://blog.csdn.net/tengweitw/article/details/17265961

作者:nineheadedbird


目录
相关文章
|
4月前
|
算法
【算法】二分查找——在排序数组中查找元素的第一个和最后一个位置
【算法】二分查找——在排序数组中查找元素的第一个和最后一个位置
|
20天前
|
搜索推荐 算法 C语言
【排序算法】八大排序(上)(c语言实现)(附源码)
本文介绍了四种常见的排序算法:冒泡排序、选择排序、插入排序和希尔排序。通过具体的代码实现和测试数据,详细解释了每种算法的工作原理和性能特点。冒泡排序通过不断交换相邻元素来排序,选择排序通过选择最小元素进行交换,插入排序通过逐步插入元素到已排序部分,而希尔排序则是插入排序的改进版,通过预排序使数据更接近有序,从而提高效率。文章最后总结了这四种算法的空间和时间复杂度,以及它们的稳定性。
64 8
|
20天前
|
搜索推荐 算法 C语言
【排序算法】八大排序(下)(c语言实现)(附源码)
本文继续学习并实现了八大排序算法中的后四种:堆排序、快速排序、归并排序和计数排序。详细介绍了每种排序算法的原理、步骤和代码实现,并通过测试数据展示了它们的性能表现。堆排序利用堆的特性进行排序,快速排序通过递归和多种划分方法实现高效排序,归并排序通过分治法将问题分解后再合并,计数排序则通过统计每个元素的出现次数实现非比较排序。最后,文章还对比了这些排序算法在处理一百万个整形数据时的运行时间,帮助读者了解不同算法的优劣。
59 7
|
2月前
|
搜索推荐 Shell
解析排序算法:十大排序方法的工作原理与性能比较
解析排序算法:十大排序方法的工作原理与性能比较
55 9
|
2月前
|
算法 搜索推荐 Java
数据结构与算法学习十三:基数排序,以空间换时间的稳定式排序,速度很快。
基数排序是一种稳定的排序算法,通过将数字按位数切割并分配到不同的桶中,以空间换时间的方式实现快速排序,但占用内存较大,不适合含有负数的数组。
26 0
数据结构与算法学习十三:基数排序,以空间换时间的稳定式排序,速度很快。
|
2月前
|
算法
❤️算法笔记❤️-(每日一刷-83、删除排序链表中的重复项)
❤️算法笔记❤️-(每日一刷-83、删除排序链表中的重复项)
32 0
|
2月前
|
存储 算法 搜索推荐
算法进阶之路:Python 归并排序深度剖析,让数据排序变得艺术起来!
算法进阶之路:Python 归并排序深度剖析,让数据排序变得艺术起来!
74 0
|
4月前
|
搜索推荐 算法 Java
现有一个接口DataOperation定义了排序方法sort(int[])和查找方法search(int[],int),已知类QuickSort的quickSort(int[])方法实现了快速排序算法
该博客文章通过UML类图和Java源码示例,展示了如何使用适配器模式将QuickSort类和BinarySearch类的排序和查找功能适配到DataOperation接口中,实现算法的解耦和复用。
44 1
现有一个接口DataOperation定义了排序方法sort(int[])和查找方法search(int[],int),已知类QuickSort的quickSort(int[])方法实现了快速排序算法
|
4月前
|
算法 搜索推荐 Java
算法实战:手写归并排序,让复杂排序变简单!
归并排序是一种基于“分治法”的经典算法,通过递归分割和合并数组,实现O(n log n)的高效排序。本文将通过Java手写代码,详细讲解归并排序的原理及实现,帮助你快速掌握这一实用算法。
43 0
|
4月前
|
算法 关系型数据库 MySQL
揭秘MySQL中的版本号排序:这个超级算法将颠覆你的排序世界!
【8月更文挑战第8天】在软件开发与数据管理中,正确排序版本号对软件更新及数据分析至关重要。因MySQL默认按字符串排序版本号,可能出现&#39;1.20.0&#39;在&#39;1.10.0&#39;之前的不合理情况。解决办法是将版本号各部分转换为整数后排序。例如,使用`SUBSTRING_INDEX`和`CAST`函数从`software`表的`version`字段提取并转换版本号,再按这些整数排序。这种方法可确保版本号按逻辑正确排序,适用于&#39;major.minor.patch&#39;格式的版本号。对于更复杂格式,需调整处理逻辑。掌握此技巧可有效应对版本号排序需求。
197 3