利用优先队列PriorityQueue实现Prim算法
2017-12-10 20:45
609 查看
1.Prim算法介绍
1.Prim算法是贪婪技术的一种。2.贪婪技术:
在每一步中,都‘贪婪’地选择最佳的操作,并希望通过一些列局部最优选择,能够产生一个整个问题(全局)的最优解。
3.Prim算法的用处:
通俗的讲就是求解最小生成树问题。
4.Prim算法思想(贪婪的体现):
Prim算法将顶点分为2个集合vt和v-vt,并总是找出边(a,b)使得a∈vt,b∈v-vt,且边的权重最小。
5.Prim算法的关键之处:
Prim算法的关键之处在于求出边(a,b)使得a∈vt,b∈v-vt,且边的权重最小。此处求权重最小的边可以用优先队列PriorityQueuen来求取。
2.代码实现
package algorithm.experiment6; import java.util.Comparator; import java.util.PriorityQueue; public class Prim { //表示无穷大 final static Integer M = Integer.MAX_VALUE; static int[][] G = { {M,3,M,M,6,5}, {3,M,1,M,M,4}, {M,1,M,6,M,4}, {M,M,6,M,8,5}, {6,M,M,8,M,2}, {5,4,4,5,2,M}}; //全部顶点名称【对应数组的下标】 static char[] vName = {'a','b','c','d','e','f'}; //顶点是否被选【对应数组的下标】 static boolean[] vIsChoose = {true,false,false,false,false,false}; public static void main(String[] args) { prim(G); } public static void prim(int[][] G) { System.out.println("默认的点:a 集合vt:a"); while(true) { //判断是否生成了最小生成树 if(isOver()) break; PriorityQueue<MyEdge> myPriorityQueue = myPriorityQueue(G,vIsChoose); MyEdge edge = myPriorityQueue.poll(); changeG(edge); // System.out.print(edge+" "); System.out.print("选择的点:"+vName[edge.index2]+" 集合vt:"); for(int i=0;i<vIsChoose.length;i++) if(vIsChoose[i]) System.out.print(vName[i]+" "); System.out.println(); } } //判断是否找到了最小生成树(判断数组vIsChoose如果全为true则返回true) public static boolean isOver() { for(Boolean b:vIsChoose){ if(!b) return false; } return true; } //改变图以及已经选择的标记数组 private static void changeG(MyEdge edge) { int x = edge.index1; int y = edge.index2; G[x][y] = M; G[y][x] = M; vIsChoose[x] = true; vIsChoose[y] = true; } //构造一个myEdge的优先队列 public static PriorityQueue<MyEdge> myPriorityQueue(int[][] G,boolean[] vIsChoose) { PriorityQueue<MyEdge> myPriorityQueue = new PriorityQueue<MyEdge>(11,myEdgeComparator()); for(int i=0;i<vIsChoose.length;i++) { //如果顶点被选则找出相邻的顶点并组成边加入到优先队列中 if(vIsChoose[i]) { //遍历相应的顶点 for(int j=0;j<G[i].length;j++) { //将相邻的顶点组成的边加入优先队列 且该边的连个顶点是包含于vt和v-vt的 if(G[i][j]!=M&&!vIsChoose[j]) { MyEdge edge = new MyEdge(i, j, G[i][j]); myPriorityQueue.offer(edge); } } } } return myPriorityQueue; } //表示边 index1:表示顶点1的在字符数组中的下标 static class MyEdge { public int index1,index2; public int weight; public MyEdge(int v1,int v2,int weight){ this.index1 = v1; this.index2 = v2; this.weight = weight; } public String toString(){ return "("+vName[index1]+","+vName[index2]+"," b10f +weight+")"; } } //myEdge比较器 public static Comparator<MyEdge> myEdgeComparator() { Comparator<MyEdge> comparator = new Comparator<MyEdge>(){ @Override public int compare(MyEdge o1, MyEdge o2) { return o1.weight-o2.weight; } }; return comparator; } }
3.运行结果
默认的点:a 集合vt:a 选择的点:b 集合vt:a b 选择的点:c 集合vt:a b c 选择的点:f 集合vt:a b c f 选择的点:e 集合vt:a b c e f 选择的点:d 集合vt:a b c d e f
4.代码分析
首先是图的表示,我采用的是邻接矩阵的方式来表示图,用vName的字符数组表示顶点名称,用vIsChoose表示相应的坐标是否被选择。内部类MyEdge用于表示边,在myPriorityQueue(int[][] G,boolean[] vIsChoose)方法中首先构建了一个优先队列,该队列通过自己实现的比较器(方法myEdgeComparator()实现)每次出队都可以得到一个满足条件的边(a,b)(权重最小,a∈vt,b∈v-vt)。依次循环直到找到最小生成树从而退出循环。
相关文章推荐
- 优先队列 PriorityQueue (用堆实现的)
- 优先队列PriorityQueue实现 大小根堆 解决top k 问题
- PriorityQueue 优先队列的实现
- 利用优先队列实现堆排序(自顶向下自底向上堆化全然二叉树的运用)
- 利用优先队列实现堆排序(自顶向下自底向上堆化完全二叉树的运用)
- go利用最小堆实现优先队列
- 利用优先队列实现的dijkstra算法
- 利用堆实现堆排序&优先队列
- 利用python的heapq实现prim算法以及优先级队列
- 利用数组和链表实现优先队列
- 利用无序数组实现优先队列并排序数组——ADT实现
- 使用并查集UnionFind和优先队列PriorityQueue实现Kruskal算法
- 利用顺序表实现优先队列的插入和删除操作
- 算法设计之,堆,堆排序,基于最大堆的最大优先队列的实现(C++实现)
- Java实现利用广度优先遍历(BFS)计算最短路径的方法
- 优先队列的数组、二叉堆实现
- 数据结构Java实现07----队列:顺序队列&顺序循环队列、链式队列、顺序优先队列
- 【C++】【STL】优先队列的实现
- 数据结构之广度优先搜索(队列实现)问题
- Java优先队列(PriorityQueue)示例