无向图的最小生成树(prim算法)

时间:2022-04-14 11:37:53

引子:


假设整个无向图中的点记为A,最小生成树中的点记为T,其他点记为Q(也就是Q= A-T),T与Q相连的边记为B

算法构造过程:

1、初始化:首先将一个点(随意一个)加入最小生成树中

2、在所有Q中找到一条与T中的某个点直接相连的并且权值最小的边B以及对应的点,加入最小生成树

3、重复以上过程,直到T=A。


无向图的最小生成树(prim算法)

 

</pre><pre name="code" class="java">package minTree;

import java.util.ArrayList;
import java.util.List;


public class MinTreeTest1 {

public static void main(String[] args) {
MinTree t = new MinTree(10);
t.addVertex("v1");
t.addVertex("v2");
t.addVertex("v3");
t.addVertex("v4");
t.addVertex("v5");
t.addVertex("v6");

t.addEdge(0, 1, 6);
t.addEdge(0, 2, 1);
t.addEdge(0, 3, 5);
t.addEdge(0, 4, 2000000);
t.addEdge(0, 5, 2000000);

t.addEdge(1, 2, 5);
t.addEdge(1, 3, 2000000);
t.addEdge(1, 4, 3);
t.addEdge(1, 5, 2000000);

t.addEdge(2, 3, 5);
t.addEdge(2, 4, 6);
t.addEdge(2, 5, 4);

t.addEdge(3, 4, 2000000);
t.addEdge(3, 5, 2);

t.addEdge(4, 5, 6);

t.printMatrix();

int[][] a = t.buildMinTree2();

System.out.println();
int size = a.length;
for(int i = 0; i < size; i++){
for(int k = 0; k < size; k++){
System.out.print(a[i][k]+"; ");
}
System.out.println();
}
}
}

class MinTree {

private int[][] matrix = null;
private Vertex[] vertexList = null;
private int size = 0;
private int maxSize = 20;


public MinTree(int maxSize) {
this.maxSize = maxSize;
this.matrix = new int[maxSize][maxSize];
this.vertexList = new Vertex[maxSize];
}

//增加顶点
public void addVertex(String label) {
if (isFull()) {
throw new ArrayIndexOutOfBoundsException("满了!!");
}
vertexList[size] = new Vertex(label, -1);
size++;
}

//增加边
public void addEdge(int start, int end, int weigth) {
if (start > size - 1 || end > size - 1) {
throw new ArrayIndexOutOfBoundsException("没有这个元素");
}

if (start == end) {
return;
}

this.matrix[start][end] = weigth;
this.matrix[end][start] = weigth;
}

public boolean isFull() {
return size == maxSize;
}

/**
* 顶点类
* @author LiangYH
*
*/
class Vertex {
String label;
int weigth;
boolean isWired;

public Vertex(String label, int weigth) {
this.label = label;
this.weigth = weigth;
this.isWired = false;
}

public void printVertex() {
System.out.println("label = " + label + "; weigth = " + weigth);
}
}

//最大权值
private static final int FLAG_WEIGTH = 10000;

/**
* 生成最小生成树
* @return 最小生成树的邻接矩阵
*/
public int[][] buildMinTree2() {
//存储最小生成树的邻接矩阵
int [][] dyadic = new int[size][size];
//存储最小生成树的顶点
List<Integer> treeList = new ArrayList<>();
//权值最小的点和边
List<DoubleVertex> tempList = new ArrayList<>();
//从第一个开始
treeList.add(0);
vertexList[0].isWired = true;
//每次循环,最小生成树将增加一个顶点
for (int j = 0; j < size; j++) {
//找到将要加入最小生成树中的点和边
int treeVertexIndex = -1;
for (int i = 0; i < treeList.size(); i++) {
treeVertexIndex = treeList.get(i);
//每次循环,会找到最小生成树中的点到其他点权值最小的边以及对应的权重
int tempWeigth = FLAG_WEIGTH;
int indexFlag = -1;
for (int k = 0; k < size; k++) {
int tempWeigth2 = matrix[treeVertexIndex][k];
if (tempWeigth2 > 0 && tempWeigth2 < tempWeigth&& !vertexList[k].isWired) {
tempWeigth = tempWeigth2;
indexFlag = k;
}
}
if (tempWeigth != FLAG_WEIGTH) {
DoubleVertex dou = new DoubleVertex(treeVertexIndex,indexFlag, tempWeigth);
tempList.add(dou);
}
}
//找到最小权值中的最小权值
DoubleVertex tempDoubleVertex = new DoubleVertex(-1, -1,FLAG_WEIGTH);
for (int i = 0; i < tempList.size(); i++) {
if (tempList.get(i).weigth < tempDoubleVertex.weigth) {
tempDoubleVertex = tempList.get(i);
}
}
if (tempDoubleVertex.weigth != FLAG_WEIGTH) {
//加入最小生成树
treeList.add(tempDoubleVertex.outTreeIndex);
//设置为已经连入最小生成树
vertexList[tempDoubleVertex.outTreeIndex].isWired = true;
//打印
System.out.println(vertexList[tempDoubleVertex.inTreeIndex].label
+ "; in Index = "+ tempDoubleVertex.inTreeIndex+
"; "+ vertexList[tempDoubleVertex.outTreeIndex].label+
"; out Index = "+ tempDoubleVertex.outTreeIndex +
"; weigth = "+ tempDoubleVertex.weigth);
//维护最小生成树的邻接矩阵
dyadic[tempDoubleVertex.inTreeIndex][tempDoubleVertex.outTreeIndex] = tempDoubleVertex.weigth;
dyadic[tempDoubleVertex.outTreeIndex][tempDoubleVertex.inTreeIndex] = tempDoubleVertex.weigth;
//清空
tempList.clear();
}
}
//还原
for(int i = 0; i < size; i++){
vertexList[i].isWired = false;
}
return dyadic;
}

//打印邻接矩阵
public void printMatrix() {

System.out.println();
for (int i = 0; i < size; i++) {
for (int k = 0; k < size; k++) {
System.out.print(matrix[i][k] + "; ");
}
System.out.println();
}
}

/**
* 记录两个顶点以及他们相连的权重
* @author admin
*
*/
class DoubleVertex {
//最小生成树中的点
int inTreeIndex;
//非最小生成树中的点
int outTreeIndex;
//权重
int weigth;

public DoubleVertex(int inTreeIndex, int outTreeIndex, int weigth) {
this.inTreeIndex = inTreeIndex;
this.outTreeIndex = outTreeIndex;
this.weigth = weigth;
}

}
}