对于图G,假设集合V是所有顶点的集合,集合E存放最小生成树所有边。现在要实现最小生成树,将实现过程中用到的顶点放入集合U。
从所有未使用的顶点v∈(V-U),和已用的顶点u∈U的边中选取权值最小的边(u,v)。将v放入U,(u,v)放入集合E。如此不断重复。当存储最小生成树
经过的顶点集合U和原顶点集合V相等时,就构造完毕。
如果prim算法是基于邻接矩阵实现的
package lc;
import java.io.IOException;
import java.util.Scanner;
public class MatrixUDG {
private char[] mVexes;
private int[][] mMatrix;
private static final int INF = Integer.MAX_VALUE;
public MatrixUDG(){
System.out.println("Please input vertex number:");
int vlen = readInt();
System.out.println("Please input edge number:");
int elen = readInt();
if(vlen<1 || elen<1 || elen>(vlen-1)*vlen){
System.out.printf("input error:invalid parameters!\n");
return;
}
mVexes = new char[vlen];
for(int i = 0;i<mVexes.length;i++){
System.out.printf("vertex(%d)",i);
mVexes[i] = readChar();
}
mMatrix = new int[vlen][vlen];
for(int i = 0;i<vlen;i++){
for(int j = 0;j<vlen;j++){
if(i == j)
mMatrix[i][j] = 0;
else
mMatrix[i][j] = INF;
}
}
for(int i = 0;i<elen;i++){
System.out.printf("edge(%d):",i);
char c1 = readChar();
char c2 = readChar();
int weight = readInt();
int p1 = getPosition(c1);
int p2 = getPosition(c2);
if(p1 == -1 || p2 == -1){
System.out.printf("input error: invalid edge!\n");
return;
}
mMatrix[p1][p2] = weight;
mMatrix[p2][p1] = weight;
}
}
public MatrixUDG(char[] Vexes,int[][] Matrix){
int vlen = Vexes.length;
mVexes = new char[vlen];
for(int i = 0;i<mVexes.length;i++){
mVexes[i] = Vexes[i];
}
mMatrix = new int[vlen][vlen];
for(int i = 0;i<vlen;i++){
for(int j = 0;j<vlen;j++){
mMatrix[i][j] = Matrix[i][j];
}
}
}
private int getPosition(char ch){
for(int i = 0;i<mVexes.length;i++){
if(mVexes[i] == ch)
return i;
}
return -1;
}
private char readChar(){
char ch = '0';
do{
try{
ch = (char) System.in.read();
}catch(IOException e){
e.printStackTrace();
}
}while(!((ch>='a'&&ch<='z')||(ch>='A'&&ch<='Z')));
return ch;
}
private int readInt(){
Scanner scanner = new Scanner(System.in);
return scanner.nextInt();
}
//返回顶点v的第一个邻接顶点索引
private int firstVertex(int v){
if(v<0 || v>(mVexes.length-1)){
return -1;
}
for(int i = 0;i<mVexes.length;i++){
if(mMatrix[v][i] != 0 && mMatrix[v][i] != INF){
//当找邻接顶点时,如果既不是自身顶点,也不是没有边的时候
return i;
}
}
return -1;
}
//返回顶点v相对于w的下一个邻接顶点的索引,失败就返回-1
private int nextVertex(int v,int w){
if(v < 0 || v > (mMatrix.length-1) || w< 0 || w>(mMatrix.length-1))
return -1;
for(int i = w + 1;i<mVexes.length;i++){
if(mMatrix[v][i] != 0 && mMatrix[v][i] != INF)
return i;
}
return -1;
}
private void dfs(int i,boolean[] visited){
visited[i] = true;
System.out.printf("%c ",mVexes[i]);
for(int w = firstVertex(i);w>=0;w = nextVertex(i,w)){
if(!visited[w])
dfs(w,visited);
}
}
public void dfs(){
boolean[] visited = new boolean[mVexes.length];
for(int i = 0;i<mVexes.length;i++){
visited[i] = false;
}
System.out.printf("dfs: ");
for(int i = 0;i<mVexes.length;i++){
if(!visited[i])
dfs(i,visited);
}
System.out.printf("\n");
}
public void print(){
System.out.printf("Matrix Graph:\n");
for(int i = 0;i<mVexes.length;i++){
for(int j = 0;j<mVexes.length;j++){
System.out.printf("%10d",mMatrix[i][j]);
}
}
System.out.printf("\n");
}
public void prim(int start) {
int num = mVexes.length;
int index = 0;
char[] prims = new char[num];
int[] weights = new int[num];
prims[index++] = mVexes[start];//原mVexes中以start为最小生成树的起点,则start位置所在的char是prim数组的第一个char值
for(int i = 0;i<num;i++){
weights[i] = mMatrix[start][i];
}//将每个顶点的权值初始化为第start个顶点到该顶点的权值。
weights[start] = 0;
for(int i = 0;i<num;i++){
if(start == i)
continue;
int j = 0;
int k = 0;
int min = INF;
//在未加入prim最小生成树的顶点集合中,选择当前顶点到未加入顶点中权值最小的边
while(j<num){
if(weights[j] != 0 && weights[j]<min){
min = weights[j];
k = j;
}
j++;
}
prims[index++] = mVexes[k];//这时prim里新加入的顶点是原mVexes中的顶点k
weights[k] = 0;
//当第k个顶点被加入到最小生成树的prims数组之后,更新其他顶点的权值。
for(j = 0;j<num;j++){
if(weights[j] != 0 && mMatrix[k][j] < weights[j]){
weights[j] = mMatrix[k][j];
}
}
}
//计算最小生成树的权值
int sum = 0;
for(int i = 1;i<index;i++){
int min = INF;
//获取prims[i]在mMatrix中的位置
int n = getPosition(prims[i]);
for(int j = 0;j<i;j++){
int m = getPosition(prims[j]);
if(mMatrix[m][n]<min)
min = mMatrix[m][n];
}
sum+=min;
}
System.out.printf("PRIM(%c)=%d ",mVexes[start],sum);
for(int i = 0;i<index;i++){
System.out.printf("%c " ,prims[i]);
}
System.out.printf("\n");//以上是打印prim最小生成树
}
public static void main(String[] args) {
char[] vexs = {'A', 'B', 'C', 'D', 'E', 'F', 'G'};
int matrix[][] = {
/*A*//*B*//*C*//*D*//*E*//*F*//*G*/
/*A*/ { 0, 12, INF, INF, INF, 16, 14},
/*B*/ { 12, 0, 10, INF, INF, 7, INF},
/*C*/ { INF, 10, 0, 3, 5, 6, INF},
/*D*/ { INF, INF, 3, 0, 4, INF, INF},
/*E*/ { INF, INF, 5, 4, 0, 2, 8},
/*F*/ { 16, 7, 6, INF, 2, 0, 9},
/*G*/ { 14, INF, INF, INF, 8, 9, 0}};
MatrixUDG pG;
// 自定义"图"(输入矩阵队列)
//pG = new MatrixUDG();
// 采用已有的"图"
pG = new MatrixUDG(vexs, matrix);
//pG.print(); // 打印图
//pG.DFS(); // 深度优先遍历
//pG.BFS(); // 广度优先遍历
pG.prim(0); // prim算法生成最小生成树
}
}
其中深度优先遍历部分也可以改成广度优先遍历
public void bfs(){
int head = 0;
int rear = 0;
int[] queue = new int[mVexes.length];
boolean[] visited = new boolean[mVexes.length];
for(int i = 0;i<mVexes.length;i++){
visited[i] = false;
}
System.out.printf("BFS: ");
for(int i = 0;i<mVexes.length;i++){
if(!visited[i]){
visited[i] = true;
System.out.printf("%c ",mVexes[i]);
queue[rear++] = i;
}
while(head != rear){
int j = queue[head++];//出队列
for(int k = firstVertex(j);k>=0;k = nextVertex(j,k)){
if(!visited[k]){
visited[k] = true;
System.out.printf("%c ",mVexes[k]);
queue[rear++] = k;
}
}
}
}
System.out.printf("\n");
}