首页 > 其他分享 >拓扑排序(TopologicalSort)

拓扑排序(TopologicalSort)

时间:2023-12-30 10:57:18浏览次数:31  
标签:int 拓扑 TopologicalSort 序列 顶点 排序 复杂度

什么是拓扑排序?

对一个有向无环图(Directed Acyclic Graph简称DAG)G进行拓扑排序,是将G中所有顶点排成一个线性序列,使得图中任意一对顶点u和v,若边<u,v>∈E(G),则u在线性序列中出现在v之前。通常,这样的线性序列称为满足拓扑次序(Topological Order)的序列,简称拓扑序列。简单的说,由某个集合上的一个偏序得到该集合上的一个全序,这个操作称之为拓扑排序。

如何实现拓扑排序?

思想:

  1. 首先选择一个入度为0的点。
  2. 从我们的AOV网(有向无环图)中,删除此顶点以及与此顶点相关联的边。
  3. 重复上述两个步骤,直到不存在入度为0的点为止。
  4. 如果选择的点数小于总的点数,那么,说明图中有环或有孤岛。否则,所有顶点的选择顺序就是我们的拓扑排序顺序。
    image
    image
    上面主要是拓扑排序的大体思想,而实现还是分为两种:
    image

DFS代码实现

时间复杂度:\(O(V+E)\) 空间复杂度:\(O(V)\)

bool dfs(int u) {
  c[u] = -1;
  for (int v = 0; v <= n; v++)
    if (G[u][v]) {
      if (c[v] < 0)
        return false;
      else if (!c[v])
        dfs(v);
    }
  c[u] = 1;
  topo.push_back(u);
  return true;
}
bool toposort() {
  topo.clear();
  memset(c, 0, sizeof(c));
  for (int u = 0; u <= n; u++)
    if (!c[u])
      if (!dfs(u)) return false;
  reverse(topo.begin(), topo.end());
  return true;
}

BFS代码实现

时间复杂度
假设这个图\(G=(V,E)\)在初始化入度为0的集合\(S\)的时候就需要遍历整个图,并检查每一条边,因而有\(O(V+E)\)的复杂度。然后对该集合进行操作,显然也是需要\(O(V+E)\)的时间复杂度。
因而总的时间复杂度就有\(O(V+E)\)

#include <bits/stdc++.h>
using namespace std;
const int M=10005;
int n,m;
int a[M]; 
vector<int> G[M];
void topo_Sort(){
	priority_queue<int,vector<int>,greater<int> >q;
	for(int i=1;i<=n;i++){
		if(a[i]==0) q.push(i);
	}
	vector<int> ans;
	while(!q.empty()){
		int id=q.top();
		q.pop();
		ans.push_back(id);
		for(int i=0;i<G[id].size();i++){
			int x=G[id][i];
			a[x]--;
			if(a[x]==0) q.push(x);
		}
	}
	if(ans.size()==n){
		for(int i=0;i<n;i++){
			printf("%d ",ans[i]);
		}
	}
	else printf("no solution");
}
int main(){
	scanf("%d %d",&n,&m);
	for(int i=1;i<=m;i++){
		int s,t;
		scanf("%d %d",&s,&t);
		G[s].push_back(t);
		a[t]++;
	}
	topo_Sort();
	return 0;
}

标签:int,拓扑,TopologicalSort,序列,顶点,排序,复杂度
From: https://www.cnblogs.com/BadBadBad/p/TopologicalSort.html

相关文章

  • 数据结构应用之桶排序
    问:有10G的订单数据,希望订单金额(假设都是正整数)进行排序,但我们内存有限,只有几百MB,如何进行排序?答:因内存有限,需要排序的数据量巨大,所以,此时需要外部排序,外部排序采用的是一种分治思想,外部排序最常用的是多路归并排序,即将大数据切成多份一次可以载入内存的小数据,对小数据进行内......
  • 排序
    冒泡排序#include<iostream>usingnamespacestd;intmain(){intarr[6]={0};intlen=sizeof(arr)/sizeof(int);for(inti=0;i<len;i++){cin>>arr[i];}//writeyourcodehere......f......
  • golang对map排序
    golang中map元素是随机无序的,所以在对maprange遍历的时候也是随机的,不像php中是按顺序。所以如果想按顺序取map中的值,可以采用以下方式:import("fmt""sort")funcmain(){m:=make(map[int]string)m[1]="a"m[2]="c"m[0]="b"......
  • 网络拓扑图怎么画最好?
    画拓扑图的方式有很多,在线软件,Visio,PPT,都是方法。问题是你要怎么从0到1,怎么样用拓扑图完美地把你的网络逻辑结构、思路呈现出来。没经验的朋友真的不知道从哪里上手。今天就给你来一篇绘制拓扑图详解,从一页白纸开始,教你怎么从0到1亲手绘制一张拓扑图。1、什么是网络拓扑(Topology)?01......
  • 排序组件
    排序组件快速使用第一步:视图类需继承GenericAPIView或其子类#以图书类为例classBookView(ViewSetMixin,ListAPIView):queryset=Book.objects.all()serializer_class=BookSerializer 第二步:导入排序类相关组件#drf内置了排序类fromrest_framework.f......
  • 算法学习笔记七一归并排序
    目录什么是归并排序算法思想代码示例什么是归并排序归并排序(MergeSort)是一种经典的排序算法,它采用分治策略来将一个大问题分解成小问题,然后将小问题的结果合并起来得到最终的解决方案。归并排序的核心思想是将待排序的数组不断地二分,直到每个子数组的长度为1,然后再将相邻的子数......
  • 插入排序
    #include<bits/stdc++.h>usingnamespacestd;inta[10005];intmain(){ intn; cin>>n; srand(time(0));//随机数发生器 for(inti=1;i<=n;i++) a[i]=rand()%100;//产生0--99的随机数 for(inti=1;i<=n-1;i++) ......
  • 简单选择排序
    定义:对n个元素进行简单选择排序的基本方法是:第一趟从第1个元素开始,在n个元素中选出最小者,将其交换至第1个位置;第二趟从第2个元素开始,在剩下的n-1个元素中选出最小者,将其交换至第2个位置,以此类推,第i趟从n-i+1个元素中选出最小元素,将其交换至第i个位置,通过n-1趟选择,最终得到非递减排......
  • 算法学习笔记六一堆排序
    目录什么是堆排序算法思想代码示例什么是堆排序堆排序(HeapSort)是一种基于二叉堆数据结构的排序算法。它的主要思想是将待排序的序列构建成一个大顶堆(或小顶堆),然后反复从堆顶取出最大(或最小)元素,将剩余的元素重新调整为一个新的堆,再重复取出堆顶元素的过程,直到排序完成。算法思......
  • 堆排序
    步骤1.将数组构建成二叉树,n的左右孩子是2n+1、2n+2.2.将二叉树转化成堆(父节点大于等于两个孩子节点(大顶堆),父节点小于等于两个孩子节点(小顶堆)),时间复杂度O(n)。3.将堆顶和最后一个元素交换(此时堆顶就是最大值),事件复杂度O(logn)。4.按需要最大的n个值来执行(n-1)次步骤3。(时......