博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Union-Find 检测无向图有无环路算法
阅读量:6281 次
发布时间:2019-06-22

本文共 4179 字,大约阅读时间需要 13 分钟。

不相交集合数据结构(Disjoint-set data structure)是一种用于跟踪集合被分割成多个不相交的子集合的数据结构,每个集合通过一个代表来标识,代表即集合中的某个成员。

Union-Find 算法为该数据结构提供了两种非常有用的操作:

  • Find:判断子集中是否存在特定的元素。可以用于检测是否两个元素存在于相同的子集中。
  • Union:将两个不子集合并成新的子集合。

Union-Find 算法的一个具体的应用就是在无向图(Undirected Graph)中检测是否存在环路(Cycle)。

例如,下面这张无向图 G:

0| \|   \1-----2

G 中包含 3 个顶点和 3 条边 {

{0, 1}, {1, 2}, {2, 1}}。

初始时,设 int[] parent = new int[VertexCount],默认每个顶点的子集中只有自己,设为 -1。

0   1  2-1 -1 -1

处理边 {0, 1},Find 顶点 0 和 1 的子集,发现它们在不同的子集中,则 Union 它们,此时 1 代表了子集 {0, 1}。

0  1  21 -1 -1

处理边 {1, 2},Find 顶点 1 和 2 的子集,发现它们在不同的子集中,则 Union 它们,此时 2 代表了子集 {0, 1, 2}。

0 1  21 2 -1

处理边 {2, 1},Find 顶点 2 和 1 的子集,发现它们在相同的子集中,则图存在环。

简单实现如下,其时间复杂度为 O(n)。

1 using System;  2 using System.Collections.Generic;  3 using System.Linq;  4   5 namespace GraphAlgorithmTesting  6 {  7   class Program  8   {  9     static void Main(string[] args) 10     { 11       Graph g = new Graph(6); 12       g.AddEdge(0, 1, 16); 13       g.AddEdge(0, 2, 13); 14       g.AddEdge(1, 2, 10); 15       g.AddEdge(1, 3, 12); 16       //g.AddEdge(2, 1, 4); 17       g.AddEdge(2, 4, 14); 18       //g.AddEdge(3, 2, 9); 19       g.AddEdge(3, 5, 20); 20       //g.AddEdge(4, 3, 7); 21       //g.AddEdge(4, 5, 4); 22  23       Console.WriteLine(); 24       Console.WriteLine("Graph Vertex Count : {0}", g.VertexCount); 25       Console.WriteLine("Graph Edge Count : {0}", g.EdgeCount); 26       Console.WriteLine(); 27  28       Console.WriteLine("Is there cycle in graph: {0}", g.HasCycle()); 29  30       Console.ReadKey(); 31     } 32  33     class Edge 34     { 35       public Edge(int begin, int end, int weight) 36       { 37         this.Begin = begin; 38         this.End = end; 39         this.Weight = weight; 40       } 41  42       public int Begin { get; private set; } 43       public int End { get; private set; } 44       public int Weight { get; private set; } 45  46       public override string ToString() 47       { 48         return string.Format( 49           "Begin[{0}], End[{1}], Weight[{2}]", 50           Begin, End, Weight); 51       } 52     } 53  54     class Graph 55     { 56       private Dictionary
> _adjacentEdges 57 = new Dictionary
>(); 58 59 public Graph(int vertexCount) 60 { 61 this.VertexCount = vertexCount; 62 } 63 64 public int VertexCount { get; private set; } 65 66 public IEnumerable
Vertices { get { return _adjacentEdges.Keys; } } 67 68 public IEnumerable
Edges 69 { 70 get { return _adjacentEdges.Values.SelectMany(e => e); } 71 } 72 73 public int EdgeCount { get { return this.Edges.Count(); } } 74 75 public void AddEdge(int begin, int end, int weight) 76 { 77 if (!_adjacentEdges.ContainsKey(begin)) 78 { 79 var edges = new List
(); 80 _adjacentEdges.Add(begin, edges); 81 } 82 83 _adjacentEdges[begin].Add(new Edge(begin, end, weight)); 84 } 85 86 private int Find(int[] parent, int i) 87 { 88 if (parent[i] == -1) 89 return i; 90 return Find(parent, parent[i]); 91 } 92 93 private void Union(int[] parent, int x, int y) 94 { 95 int xset = Find(parent, x); 96 int yset = Find(parent, y); 97 parent[xset] = yset; 98 } 99 100 public bool HasCycle()101 {102 int[] parent = new int[VertexCount];103 for (int i = 0; i < parent.Length; i++)104 {105 parent[i] = -1;106 }107 108 // Iterate through all edges of graph, find subset of both109 // vertices of every edge, if both subsets are same, 110 // then there is cycle in graph.111 foreach (var edge in this.Edges)112 {113 int x = Find(parent, edge.Begin);114 int y = Find(parent, edge.End);115 116 if (x == y)117 {118 return true;119 }120 121 Union(parent, x, y);122 }123 124 return false;125 }126 }127 }128 }

本篇文章《》由  发表自,未经作者本人同意禁止任何形式的转载,任何自动或人为的爬虫转载行为均为耍流氓。

你可能感兴趣的文章
时间戳解读
查看>>
sbin/hadoop-daemon.sh: line 165: /tmp/hadoop-hxsyl-journalnode.pid: Permission denied
查看>>
@RequestMapping 用法详解之地址映射
查看>>
254页PPT!这是一份写给NLP研究者的编程指南
查看>>
《Data Warehouse in Action》
查看>>
String 源码浅析(一)
查看>>
Spring Boot 最佳实践(三)模板引擎FreeMarker集成
查看>>
Fescar 发布 0.2.3 版本,支持 Redis 和 Apollo
查看>>
Google MapReduce到底解决什么问题?
查看>>
CCNP-6 OSPF试验2(BSCI)
查看>>
Excel 2013 全新的图表体验
查看>>
openstack 制作大于2TB根分区自动扩容的CENTOS镜像
查看>>
Unbuntu安装遭遇 vmware上的Easy install模式
查看>>
几个常用的ASP木马
查看>>
python分析postfix邮件日志的状态
查看>>
Mysql-5.6.x多实例配置
查看>>
psutil
查看>>
在git@osc上托管自己的代码
查看>>
机器学习算法:朴素贝叶斯
查看>>
小五思科技术学习笔记之扩展访问列表
查看>>