|
| 1 | +package minimal_spanning_tree; |
| 2 | + |
| 3 | +import java.io.InputStream; |
| 4 | +import java.util.ArrayList; |
| 5 | +import java.util.Arrays; |
| 6 | +import java.util.HashMap; |
| 7 | +import java.util.List; |
| 8 | +import java.util.Map; |
| 9 | +import java.util.Scanner; |
| 10 | + |
| 11 | +/** |
| 12 | + * 最小生成树的prim算法,从一个节点出发,每次找到与所有加入的节点相邻的节点, |
| 13 | + * 权重最小的节点(之前没有加入过)加入,不能形成环。 |
| 14 | + * |
| 15 | + * @author liyafei |
| 16 | + * |
| 17 | + */ |
| 18 | +public class MSTPrim { |
| 19 | + |
| 20 | + List list = new ArrayList<>(); |
| 21 | + int count = 1; |
| 22 | + double[][] weights; |
| 23 | + |
| 24 | + class Node { |
| 25 | + Node link; |
| 26 | + Node pre; |
| 27 | + int weight; |
| 28 | + int key; |
| 29 | + int start; |
| 30 | + int end; |
| 31 | + } |
| 32 | + |
| 33 | + /** |
| 34 | + * prim 算法求最小生成树,给定根节点,开始找相邻节点的最小值,算法每一步在连接集合A和A之外的节点的所有边中 选择一条轻量级边加入到A中 |
| 35 | + * 用一个列表将遍历过的轻量级边的节点存储起来,然后看新的轻量级边的两点是否在列表中,如果在,就不加入。 |
| 36 | + * |
| 37 | + * @param r 起始节点 注 意:图的矩阵表示形式是对称的,可以利用 |
| 38 | + */ |
| 39 | + public void mstprim(int r) { |
| 40 | + List list2 = new ArrayList<>(); |
| 41 | +// for (int i = 0; i < weights.length; i++) { |
| 42 | +// Node node = (Node) list.get(i); |
| 43 | +// node.key = Integer.MAX_VALUE; |
| 44 | +// node.pre = null; |
| 45 | +// } |
| 46 | +// // Node node=(Node) list.get(r); |
| 47 | + // node.key=0; |
| 48 | + |
| 49 | + // double[] arr=weights[r-1]; //取出给定顶点相邻节点的权重值,然后找出几行几列。排序 |
| 50 | + // double min = Double.MAX_VALUE; |
| 51 | + // int index=0; //角标值 |
| 52 | + // for (int i = 0; i < arr.length; i++) { |
| 53 | + // if(arr[i]>0 && arr[i]<min){ |
| 54 | + // min=arr[i]; |
| 55 | + // index=i; |
| 56 | + // } |
| 57 | + // } |
| 58 | + // (r,index)这条线被包括进来了 |
| 59 | + // list2.add(r); |
| 60 | + // if(!list2.contains(index)){ |
| 61 | + // list2.add(index); |
| 62 | + // } |
| 63 | +// Map map = new HashMap(); |
| 64 | + list2.add(r); |
| 65 | + List list3 = new ArrayList<>(); |
| 66 | + while (list2.size() < list.size()) { |
| 67 | + double minest = Double.MAX_VALUE; |
| 68 | + int index2 = 0; |
| 69 | + // List list4=new ArrayList<>(); |
| 70 | + int[] arr = new int[2]; |
| 71 | + for (int i = 0; i < list2.size(); i++) { |
| 72 | + double[] arr2 = weights[(int) list2.get(i)]; |
| 73 | + int key = (int) list2.get(i); |
| 74 | + for (int j = 0; j < arr2.length; j++) { |
| 75 | + if (arr2[j] > 0 && arr2[j] < minest) { |
| 76 | + // System.out.println("j "+j); |
| 77 | + // System.out.println("arr2 "+arr2[j]); |
| 78 | + if (!list2.contains(j)) { |
| 79 | + minest = arr2[j]; |
| 80 | + index2 = j; |
| 81 | +// map.put(key, index2); |
| 82 | + |
| 83 | + // 找个数据结构将(key,index2)存储起来 |
| 84 | + arr[0] = key; |
| 85 | + arr[1] = index2; //key是最小生成树的上一节点(从遍历过的所有节点中选出),index2最小生成树的下一节点。 |
| 86 | + // list4.add(key); |
| 87 | + // list4.add(index2); |
| 88 | + // System.out.println(index2); |
| 89 | + } |
| 90 | + } |
| 91 | + } |
| 92 | + } |
| 93 | + list3.add(arr);// 存储路径,里面使用列表存储了经过的路径(key,index2) |
| 94 | + list2.add(index2); |
| 95 | + } |
| 96 | + |
| 97 | + // double[] weis=weights[index]; |
| 98 | + // double[][] afteriter=new double[2][weights.length]; |
| 99 | + // afteriter[0]=arr; |
| 100 | + // afteriter[1]=weis; |
| 101 | + for (int i = 0; i < list2.size(); i++) { |
| 102 | +// System.out.println("key " + list2.get(i)); |
| 103 | + // System.out.println("value "+map.get(list2.get(i))); |
| 104 | + } |
| 105 | + double sum = 0; |
| 106 | + int index3; |
| 107 | + int index4; |
| 108 | + System.out.println("最小生成树经过的路径为"); |
| 109 | + for (int i = 0; i < list3.size(); i++) { |
| 110 | + // index3=(int) list2.get(i); |
| 111 | + // index4=(int) list2.get((i+1)); |
| 112 | + // sum=sum+weights[index3][index4]; //总路径 |
| 113 | + int[] arr = (int[]) list3.get(i); |
| 114 | + |
| 115 | + index3 = arr[0]; |
| 116 | + index4 = arr[1]; |
| 117 | + sum = sum + weights[index3][index4]; |
| 118 | + System.out.println("从节点"+index3+"到节点"+index4+", 长度为"+weights[index3][index4]); |
| 119 | + } |
| 120 | + System.out.println("总的最短路径为"+sum); |
| 121 | + // System.out.println(list2.size()); |
| 122 | + // System.out.println(min); |
| 123 | + // System.out.println(index); |
| 124 | + // |
| 125 | + } |
| 126 | + |
| 127 | + /** |
| 128 | + * 得到创建的带有权重的图,读出相邻节点之间的距离,然后存储到二维数组weights中。 |
| 129 | + * 权重图的大小比节点多1,但是角标为0的位置都没用,为了处理存储的位置与节点的编号相一致 |
| 130 | + */ |
| 131 | + public double[][] getWeightArray() { |
| 132 | + weights = new double[list.size()][list.size()]; |
| 133 | + for (int i = 0; i < list.size(); i++) { |
| 134 | + Node node = (Node) list.get(i); |
| 135 | + while (node != null) { |
| 136 | + int row = node.start - 1; |
| 137 | + int col = node.end - 1; |
| 138 | + double weight = node.weight; |
| 139 | + weights[row][col] = weight; |
| 140 | + node = node.link; |
| 141 | + } |
| 142 | + |
| 143 | + } |
| 144 | + return weights; |
| 145 | + } |
| 146 | + |
| 147 | + /** |
| 148 | + * 打印权重图 |
| 149 | + */ |
| 150 | + public void printWeightGraph() { |
| 151 | + double[][] weightsArray = getWeightArray(); |
| 152 | + for (int i = 0; i < weightsArray.length; i++) { |
| 153 | + |
| 154 | + double[] wa = weightsArray[i]; |
| 155 | + for (int j = 0; j < wa.length; j++) { |
| 156 | + System.out.print(wa[j] + " "); |
| 157 | + } |
| 158 | + System.out.println(); |
| 159 | + } |
| 160 | + System.out.println(); |
| 161 | + } |
| 162 | + |
| 163 | + /** |
| 164 | + * 先构建带有权重的无向图。 |
| 165 | + */ |
| 166 | + public List createGraph() { |
| 167 | + Class clazz = this.getClass(); |
| 168 | + InputStream ins = clazz.getResourceAsStream("/data.txt"); |
| 169 | + Scanner scanner = new Scanner(ins); |
| 170 | + |
| 171 | + while (scanner.hasNextLine()) { |
| 172 | + String s1 = scanner.nextLine(); |
| 173 | + Scanner oneLine = new Scanner(s1); |
| 174 | + Node newNode; |
| 175 | + Node first = null; |
| 176 | + Node last = null; |
| 177 | + while (oneLine.hasNext()) { |
| 178 | + String s2 = oneLine.next(); |
| 179 | + int end = Integer.parseInt(s2); |
| 180 | + if (end == 999) { |
| 181 | + break; |
| 182 | + } |
| 183 | + newNode = new Node(); |
| 184 | + if (first != null && oneLine.hasNext()) { |
| 185 | + String s3 = oneLine.next(); |
| 186 | + int weight = Integer.parseInt(s3); |
| 187 | + newNode.weight = weight; |
| 188 | + } |
| 189 | + newNode.start = count; |
| 190 | + newNode.end = end; |
| 191 | + newNode.link = null; |
| 192 | + if (first == null) { |
| 193 | + first = newNode; |
| 194 | + last = newNode; |
| 195 | + } else { |
| 196 | + last.link = newNode; |
| 197 | + last = newNode; |
| 198 | + } |
| 199 | + } |
| 200 | + list.add(first); |
| 201 | + count++; |
| 202 | + } |
| 203 | + return list; |
| 204 | + } |
| 205 | + |
| 206 | +} |
0 commit comments