最小生成树-----普里姆算法---java版

最小生成树(自己理解的,不当之处希望有人可以指出)

简单的说一下最小生成树:

假设一个图,它有n个顶点,则只需n-1条边,就可以将其组成一个连通图,在各种组合中,所有n-1条边的权重之和最小的连通图,就是所谓的最小生成树.

算法思想(自己揣摩的,不当之处希望有人可以指出)

如上图,我们以v0为起点对整个图求其最小生成树,过程如下:

首先既然以v0开始,那么v0肯定就加入到了最小生成树中,然后计算v0距离其他各个顶点的距离.不连通的以无穷大表示,则得到vo距离其他各个顶点距离如下:

这代表什么意思呢?

其实很简单,就是与v0相连通的点只有v1和v11,而最小生成树要求v0必须要与图中其他n-1个中的某一个点进行连通,且权重值最小,因此很自然而然的我们会让v0和v1连接起来

按照普里姆算法的思想既然V0和v1这条边已经确定了,且v0与其他各个顶点的权重值也知道了,我们这个时候可以继续考虑一下v1的连通情况及其权重大小 ,同时由于v0和v1已经确定了,我们就先不管他们了,将其值可以都设为0,则:

 

上图中得到的这个数组表示什么意思呢?其实很好理解,就是v0和v1两个顶点与其它各个顶点的连通性与权重.

那这个东东有什么用呢?这时候我们就要有一个整体的思想,为了保证连通性以及权重最小,vo和v1两个已经确定了的点肯定要与其它的点进行连接,而上面的数组列出了所有与v0以及v1相连通的点,只要选最小的那个,我们就找到了答案.

重复上面两个步骤,就得到了满足要求的最小生成树.

package cn.nrsc.graph;

public class Graph_Prim {
	// ----------------------------图的表示方式------------------------
	private int vertexSize;// 顶点的数量
	private int[] vertexs;// 顶点对应的数组
	private int[][] matrix;// 邻接矩阵
	private static final int MAX_WEIGHT = 1000;// 代表顶点之间不连通
	private boolean[] isVisited; // 顶点是否已经被访问

	public Graph_Prim(int vertexSize) {
		this.vertexSize = vertexSize;
		this.matrix = new int[vertexSize][vertexSize];
		this.vertexs = new int[vertexSize];
		for (int i = 0; i < vertexSize; i++) {
			vertexs[i] = i;
		}

		isVisited = new boolean[vertexSize];
	}
	// ----------------------------图的表示方式------------------------

	// 最小生成树----普里姆算法
	public void prim() {
		// 假设最先取出顶点0,并遍历出它与其他所有顶点的距离----正好就是图中邻接矩阵的第一行
		int[] distance = matrix[0];

		int sum = 0; // 总距离

		System.out.print("查找到点的顺序:0");

		// 控制向树中添加点的次数
		// 因为默认取出了一个点加入到了最小生成树中,则还需要再确定另外n-1个点的加入顺序
		for (int i = 1; i < vertexSize; i++) {
			// 假设初始最小值如下:
			int min = MAX_WEIGHT;
			int minId = 0;

			// 遍历距离数组找出该数组中除了距离为0(说明该点已经加入到了最小生成树中)和距离为无穷大的
			// 所有顶点中距离最小的那个----说明这个点是与已经确定的所有点可以连通,而且值最小
			for (int j = 1; j < vertexSize; j++) {
				if (distance[j] > 0 && distance[j] < MAX_WEIGHT && distance[j] < min) {
					min = distance[j];
					minId = j;
				}
			}

			// 将minId标定为已经确定的点
			distance[minId] = 0;

			System.out.print("--->" + minId);
			// 计算总距离
			sum += min;

			// 遍历minId点的所有邻接点,找到已确定点到其他未知点之间更小的距离
			// 0肯定不用再遍历了,因为第一个确定的点就是它,所以从1开始
			for (int k = 1; k < vertexSize; k++) {
				if (distance[k] > 0 && distance[k] > matrix[minId][k]) {
					distance[k] = matrix[minId][k];
				}
			}
		}
		System.out.println();
		System.out.println("最小生成树的总距离为:" + sum);

	}
	// 最小生成树----普里姆算法

	public static void main(String[] args) {
		Graph_Prim graph = new Graph_Prim(9);
		int[] v0 = { 0, 10, MAX_WEIGHT, MAX_WEIGHT, MAX_WEIGHT, 11, MAX_WEIGHT, MAX_WEIGHT, MAX_WEIGHT };
		int[] v1 = { 10, 0, 18, MAX_WEIGHT, MAX_WEIGHT, MAX_WEIGHT, 16, MAX_WEIGHT, 12 };
		int[] v2 = { MAX_WEIGHT, MAX_WEIGHT, 0, 22, MAX_WEIGHT, MAX_WEIGHT, MAX_WEIGHT, MAX_WEIGHT, 8 };
		int[] v3 = { MAX_WEIGHT, MAX_WEIGHT, 22, 0, 20, MAX_WEIGHT, 24, 16, 21 };
		int[] v4 = { MAX_WEIGHT, MAX_WEIGHT, MAX_WEIGHT, 20, 0, 26, MAX_WEIGHT, 7, MAX_WEIGHT };
		int[] v5 = { 11, MAX_WEIGHT, MAX_WEIGHT, MAX_WEIGHT, 26, 0, 17, MAX_WEIGHT, MAX_WEIGHT };
		int[] v6 = { MAX_WEIGHT, 16, MAX_WEIGHT, 24, MAX_WEIGHT, 17, 0, 19, MAX_WEIGHT };
		int[] v7 = { MAX_WEIGHT, MAX_WEIGHT, MAX_WEIGHT, 16, 7, MAX_WEIGHT, 19, 0, MAX_WEIGHT };
		int[] v8 = { MAX_WEIGHT, 12, 8, 21, MAX_WEIGHT, MAX_WEIGHT, MAX_WEIGHT, MAX_WEIGHT, 0 };

		graph.matrix[0] = v0;
		graph.matrix[1] = v1;
		graph.matrix[2] = v2;
		graph.matrix[3] = v3;
		graph.matrix[4] = v4;
		graph.matrix[5] = v5;
		graph.matrix[6] = v6;
		graph.matrix[7] = v7;
		graph.matrix[8] = v8;
		
		//test
		graph.prim();

	}
}

猜你喜欢

转载自blog.csdn.net/nrsc272420199/article/details/82899932
今日推荐