算法:权重图的最最小生成树算法
算法思路
问题
给定顶点集合为 V,边集合为 E,求最小生成树 T?
解过程
任意时刻的边都可以划分为到三个集合:
- X:边的所有顶点都是最小生成树的一部分。
- Y:边的末端节点不是最小生成树的一部分。
- Z:其它。
从 Y 中选择权重最小的边,将其加入到 T 中。
优先级队列
该算法需要用到一个工具:优先级队列(从某个集合中选择最小的元素)。
1 class PriorityQueue<T>2 where T : IComparable<T>3 {4 private T[] _items;5 private int _length;6 7 public PriorityQueue(int size)8 {9 _items = new T[size];10 }11 12 public void EnQueue(T item)13 {14 if (this.IsFull())15 {16 throw new InvalidOperationException("容量已满,不能插入!");17 }18 19 _items[_length++] = item;20 this.MoveUp(_length - 1);21 }22 23 private void MoveUp(int index)24 {25 var bottom = _items[index];26 var current = index;27 28 while (current > 0)29 {30 var parent = (current - 1) / 2;31 if (_items[parent].CompareTo(bottom) < 0)32 {33 break;34 }35 36 _items[current] = _items[parent];37 current = parent;38 }39 40 _items[current] = bottom;41 }42 43 public T DeQueue()44 {45 if (this.IsEmpty())46 {47 throw new InvalidOperationException("容量已空,不能删除!");48 }49 50 var result = _items[0];51 _items[0] = _items[--_length];52 53 this.MoveDown(0);54 55 return result;56 }57 58 private void MoveDown(int index)59 {60 var top = _items[index];61 var current = index;62 63 while (current < _length)64 {65 var small = 0;66 var left = 2 * current + 1;67 var right = left + 1;68 69 if (left < _length && right < _length)70 {71 if (_items[left].CompareTo(_items[right]) <= 0)72 {73 small = left;74 }75 else76 {77 small = right;78 }79 }80 else if (left < _length)81 {82 small = left;83 }84 else85 {86 break;87 }88 89 if (_items[small].CompareTo(top) >= 0)90 {91 break;92 }93 94 _items[current] = _items[small];95 current = small;96 }97 98 _items[current] = top;99 } 100 101 public bool IsFull() 102 { 103 return _length == _items.Length; 104 } 105 106 public bool IsEmpty() 107 { 108 return _length == 0; 109 } 110 }
最小生成树代码
1 class Edge : IComparable<Edge>2 {3 public int StartIndex { get; set; }4 5 public int EndIndex { get; set; }6 7 public int Weight { get; set; }8 9 public string Description { get; set; }10 11 public int CompareTo(Edge other)12 {13 return this.Weight.CompareTo(other.Weight);14 }15 }16 17 private class Path : IComparable<Path>18 {19 public Path()20 {21 this.Edges = new List<Edge>();22 }23 24 public int StartVertexIndex { get; set; }25 26 public int EndVertexIndex { get; set; }27 28 public List<Edge> Edges { get; private set; }29 30 public int Weight { get; private set; }31 32 public void AddEdges(IEnumerable<Edge> edges)33 {34 foreach (var edge in edges)35 {36 this.AddEdge(edge);37 }38 }39 40 public void AddEdge(Edge edge)41 {42 this.Edges.Add(edge);43 this.Weight += edge.Weight;44 }45 46 public int CompareTo(Path other)47 {48 return this.Weight.CompareTo(other.Weight);49 }50 }51 52 class Vertex<T>53 {54 public T Value { get; set; }55 }56 57 class Graph<T>58 {59 #region 私有字段60 61 private int _maxSize;62 private Vertex<T>[] _vertexs;63 private Edge[][] _edges;64 private int _vertexCount = 0;65 66 #endregion67 68 #region 构造方法69 70 public Graph(int maxSize)71 {72 _maxSize = maxSize;73 _vertexs = new Vertex<T>[_maxSize];74 _edges = new Edge[_maxSize][];75 for (var i = 0; i < _maxSize; i++)76 {77 _edges[i] = new Edge[_maxSize];78 }79 }80 81 #endregion82 83 #region 添加顶点84 85 public Graph<T> AddVertex(T value)86 {87 _vertexs[_vertexCount++] = new Vertex<T> { Value = value };88 89 return this;90 }91 92 #endregion93 94 #region 添加边95 96 public Graph<T> AddUnDirectedEdge(T startItem, T endItem, int weight)97 {98 var startIndex = this.GetVertexIndex(startItem);99 var endIndex = this.GetVertexIndex(endItem); 100 101 _edges[startIndex][endIndex] = new Edge { StartIndex = startIndex, EndIndex = endIndex, Weight = weight, Description = String.Format("{0}->{1}", startItem, endItem) }; 102 _edges[endIndex][startIndex] = new Edge { StartIndex = endIndex, EndIndex = startIndex, Weight = weight, Description = String.Format("{0}->{1}", endItem, startItem) }; 103 104 return this; 105 } 106 107 public Graph<T> AddDirectedEdge(T startItem, T endItem, int weight) 108 { 109 var startIndex = this.GetVertexIndex(startItem); 110 var endIndex = this.GetVertexIndex(endItem); 111 112 _edges[startIndex][endIndex] = new Edge { StartIndex = startIndex, EndIndex = endIndex, Weight = weight, Description = String.Format("{0}->{1}", startItem, endItem) }; 113 114 return this; 115 } 116 117 #endregion 118 119 #region 最小生成树 120 121 public IEnumerable<Edge> GetMinimumSpanningTree() 122 { 123 var minimumSpanningTrees = new List<Edge>(); 124 Dictionary<int, bool> vertexInTreesTracker = new Dictionary<int, bool>(); 125 var queue = new PriorityQueue<Edge>(_maxSize); 126 127 var currentVertexIndex = 0; 128 while (minimumSpanningTrees.Count < _vertexCount - 1) 129 { 130 vertexInTreesTracker[currentVertexIndex] = true; 131 132 foreach (var item in _edges[currentVertexIndex]) 133 { 134 if (item == null) 135 { 136 continue; 137 } 138 if (vertexInTreesTracker.ContainsKey(item.EndIndex)) 139 { 140 continue; 141 } 142 143 queue.EnQueue(item); 144 } 145 146 var smallEdge = queue.DeQueue(); 147 while (vertexInTreesTracker.ContainsKey(smallEdge.EndIndex)) 148 { 149 smallEdge = queue.DeQueue(); 150 } 151 minimumSpanningTrees.Add(smallEdge); 152 currentVertexIndex = smallEdge.EndIndex; 153 } 154 155 return minimumSpanningTrees; 156 } 157 158 #endregion 159 160 #region 最短路径 161 162 public IEnumerable<Edge> GetShortestPath(T startItem, T endItem) 163 { 164 var startIndex = this.GetVertexIndex(startItem); 165 var endIndex = this.GetVertexIndex(endItem); 166 167 var shortestPaths = new Dictionary<int, Path>(); 168 var queue = new PriorityQueue<Path>(_maxSize); 169 170 var currentVertexIndex = startIndex; 171 var currentPath = new Path 172 { 173 StartVertexIndex = startIndex, 174 EndVertexIndex = endIndex 175 }; 176 177 while (!shortestPaths.ContainsKey(endIndex)) 178 { 179 foreach (var item in _edges[currentVertexIndex]) 180 { 181 if (item == null) 182 { 183 continue; 184 } 185 if (shortestPaths.ContainsKey(item.EndIndex)) 186 { 187 continue; 188 } 189 190 var path = new Path 191 { 192 StartVertexIndex = startIndex, 193 EndVertexIndex = item.EndIndex 194 }; 195 path.AddEdges(currentPath.Edges); 196 path.AddEdge(item); 197 queue.EnQueue(path); 198 } 199 200 var smallPath = queue.DeQueue(); 201 while (shortestPaths.ContainsKey(smallPath.EndVertexIndex)) 202 { 203 smallPath = queue.DeQueue(); 204 } 205 shortestPaths[smallPath.EndVertexIndex] = smallPath; 206 currentVertexIndex = smallPath.EndVertexIndex; 207 currentPath = smallPath; 208 } 209 210 return shortestPaths[endIndex].Edges; 211 } 212 213 #endregion 214 215 #region 帮助方法 216 217 private int GetVertexIndex(T item) 218 { 219 for (var i = 0; i < _vertexCount; i++) 220 { 221 if (_vertexs[i].Value.Equals(item)) 222 { 223 return i; 224 } 225 } 226 return -1; 227 } 228 229 #endregion 230 }
备注
最短路径的算法和最小生成树的算法非常相似,都是利用了:优先级队列。
转载于:https://www.cnblogs.com/happyframework/p/3497306.html
算法:权重图的最最小生成树算法相关推荐
- python棋盘最短路径_Python数据结构与算法之图的最短路径(Dijkstra算法)完整实例...
本文实例讲述了Python数据结构与算法之图的最短路径(Dijkstra算法).分享给大家供大家参考,具体如下: # coding:utf-8 # Dijkstra算法--通过边实现松弛 # 指定一个 ...
- matlab求kcf算法响应图_matlab求kcf算法响应图_剖析KCF
来源自我的博客 前言 核相关滤波算法是单目标跟踪领域一个举足轻重的算法,而kernelized correlation filters(KCF)是其原始形态,下面我以一个小白的角度慢慢揭开其神秘面纱. ...
- 算法导论-上课笔记10:最小生成树
文章目录 0 前言 1 最小生成树 2 Kruskal算法 3 Prim算法 0 前言 在电路设计中,常常需要将多个组件的针脚连接在一起.要连接n个针脚,可以使用n-1根连线,每根连线连接两个针脚,则 ...
- 多机器人路径规划的代码_知荐 | 地平线机器人算法工程师总结六大路径规划算法...
来源 | 知乎 知圈 | 进"高精度地图社群",请加微信15221054164,备注地图 目录 1 自主机器人近距离操作运动规划体系········1.1 单个自主机器人的规划体系 ...
- 算法:图(Graph)的遍历、最小生成树和拓扑排序
背景 不同的数据结构有不同的用途,像:数组.链表.队列.栈多数是用来做为基本的工具使用,二叉树多用来作为已排序元素列表的存储,B 树用在存储中,本文介绍的 Graph 多数是为了解决现实问题(说到底, ...
- 证明kruskal算法求解图的最小生成树具有贪心选择性质_将并查集应用在图论中的最小生成树算法——Kruskal...
点击上方蓝字,和我一起学技术. 今天是算法和数据结构专题的第19篇文章,我们一起来看看最小生成树. 我们先不讲算法的原理,也不讲一些七七八八的概念,因为对于初学者来说,看到这些术语和概念往往会很头疼. ...
- 算法:通过克鲁斯卡尔(Kruskal)算法,求出图的最小生成树
之前我给大家分享过用普利姆(Prim)算法来求出图的最小生成树(点我去看看),今天我再给大家分享一个也是求图的最小生成树的克鲁斯卡尔(Kruskal)算法 克鲁斯卡尔(Kruskal)算法,就相当于先 ...
- 数据结构与算法——31. 图的应用:拓扑排序、强连通分支、最短路径问题、最小生成树
文章目录 一.拓扑排序(Topological Sort) 实现思路 二.强连通分支 1. 转置的概念 2. 强连通分支算法:Kosaraju算法思路 三.最短路径问题 1. 最短路径问题:Dijks ...
- 图的最小生成树算法实现(Prim + Kruskal)
1.采用书上第 161 页定义的图的邻接矩阵存储表示,编程实现构造最小生成树的 Prim 算法. 2.采用书上第 161 页定义的图的邻接矩阵存储表示,编程实现构造最小生成树的 Kruskal 算法. ...
最新文章
- python定义一个汽车类_汽车类Python程序
- 用Python解锁“吃鸡”正确姿势
- !!导致大智慧公式总是死循环的编码风格
- 测试C语言malloc申请内存不释放结果
- win8 linux分区工具,Ubuntu下挂载Win8磁盘分区
- Golang——包引入和闭包
- conda deactivate python3_conda进行python环境隔离
- 计算机视觉新范式: Transformer
- Python求数独的补充
- (day05)剑指 Offer 11. 旋转数组的最小数字-(二分法)
- bootstrap 模态框modal
- 【预测模型】基于matlab BP神经网络预测【含Matlab源码 221期】
- (超详细)算法学习:STL和基本数据结构
- c语言素数环实验报告,c语言素数环问题实例讲解
- jQuery 仿抖音时钟罗盘转动效果
- 数据库实验八--OpenGauss(数据库的备份与恢复)
- Windows + Linux 双系统 卸载 Liunx
- Unknown label type: ‘continuous
- HTML/CSS class6 table布局
- 场景调研 persona
热门文章
- 老男孩python爬虫视频教程_python爬虫入门
- C语言程序care用法,词汇精选:care的用法和辨析
- 如何明智的使用计算机,幼儿园如何正确使用计算机
- (12)Verilog HDL可综合与不可综合区别(第3天)
- (6)FPGA面试技能提升篇(OpenCV)
- bind mysql django_Django+bind dlz DNS管理平台
- java中类定义修饰符_Java 中类和方法修饰符
- STM32F103:三.(3)MPU6050
- 3.FreeRTOS学习笔记-任务
- boost::asio