//最小生成树定义:n个顶点,n-1条边连接,路径之和最小
//算法思想:先取一个顶点,找可能路径最小的边,然后这2个顶点对剩余顶点的边中取最小的,以此进行下去,最后就是最小生成树
class Edge {
int start;
int end;
int distance;
public Edge(int s, int e, int d) {
start = s;
end = e;
distance = d;
}
}
//优先级队列,实际中会用堆代替基于数组或链表的队列吧
class PQueue {
final int size;
int curSize;
Edge[] array;
public PQueue(int size) {
this.size = size;
curSize = 0;
array = new Edge[size];
}
// 从大到小
public void add(Edge e) {
int i;
for (i = 0; i < curSize; i++)
if (e.distance >= array[i].distance)
break;
for (int j = curSize - 1; j >= i; j--) {
array[j + 1] = array[j];
}
array[i] = e;
curSize++;
}
public Edge removeMin() {
return array[--curSize];
}
public void removeN(int n) {
for (int j = n; j < curSize - 1; j++)
array[j] = array[j + 1];
curSize--;
}
public int size() {
return curSize;
}
public Edge peekN(int n) {
return array[n];
}
public int find(int index) {
for (int j = 0; j < curSize; j++)
if (array[j].end == index)
return j;
return -1;
}
}
class Vertex {
char label;
boolean inTree;
public Vertex(char label) {
this.label = label;
inTree = false;
}
}
public class Graph {
private final int noEdge = -1;// 如果没有边,距离设置为-1
private final int maxVer;
private Vertex[] vertex;
private int[][] adjMat;
private int curVer;// 当前顶点index
private int nVers;// 当前顶点数
private int nTree;// 在树中的顶点数
private PQueue queue;
public Graph(int size) {
nTree = 0;
nVers = 0;
maxVer = size;
vertex = new Vertex[maxVer];
queue = new PQueue(maxVer);
adjMat = new int[maxVer][maxVer];
for (int i = 0; i < maxVer; i++)
for (int j = 0; j < maxVer; j++)
adjMat[i][j] = noEdge;// 初始值
}
public void addVer(char label) {
vertex[nVers++] = new Vertex(label);
}
// 假设无向
public void addEdge(int ver1, int ver2, int distance) {
if (ver1 == ver2)
return;
adjMat[ver1][ver2] = distance;
adjMat[ver2][ver1] = distance;
}
public void displayVer(int key) {
System.out.print(vertex[key].label);
}
public void mst() {
curVer = 0;// 这个起始点是任意的,0-5全试过
while (nTree < nVers - 1) {
vertex[curVer].inTree = true;
nTree++;
for (int j = 0; j < nVers; j++) {
if (j == curVer)// 排除自己
continue;
if (vertex[j].inTree)// 已经在队列中
continue;
int distance = adjMat[curVer][j];
if (distance == noEdge)// 如果2个顶点无边
continue;
putInQueue(j, distance);
}
if (queue.size() == 0) {
System.out.println("graph has not been connected");
return;
}
Edge edge = queue.removeMin();
int start = edge.start;
curVer = edge.end;
System.out.print(vertex[start].label);
System.out.print(vertex[curVer].label);
System.out.println();
}
for (int i = 0; i < nVers; i++) {
vertex[i].inTree = false;
}
}
private void putInQueue(int j, int distance) {
int index = queue.find(j);
if (index != -1) {
Edge edge = queue.peekN(index);
int oldDist = edge.distance;
// 如果队列里最大的距离大于添加的距离,就移除它,因为每次选最小距离
// 而如果要添加的距离大于等于它,则不予添加
if (oldDist > distance) {
queue.removeN(index);
Edge newEdge = new Edge(curVer, j, distance);
queue.add(newEdge);
}
} else {// 如果队列里没有以j为终点的边,直接添加
Edge edge = new Edge(curVer, j, distance);
queue.add(edge);
}
}
public static void main(String[] args) {
Graph g = new Graph(20);
g.addVer('A');
g.addVer('B');
g.addVer('C');
g.addVer('D');
g.addVer('E');
g.addVer('F');
g.addEdge(0, 1, 6);
g.addEdge(0, 3, 4);
g.addEdge(1, 2, 10);
g.addEdge(1, 3, 7);
g.addEdge(1, 4, 7);
g.addEdge(2, 3, 8);
g.addEdge(2, 4, 5);
g.addEdge(2, 5, 6);
g.addEdge(3, 4, 12);
g.addEdge(4, 5, 7);
g.mst();
}
}
//算法思想:先取一个顶点,找可能路径最小的边,然后这2个顶点对剩余顶点的边中取最小的,以此进行下去,最后就是最小生成树
附上一个讲的很好的链接https://blog.csdn.net/luoshixian099/article/details/51908175
//边class Edge {
int start;
int end;
int distance;
public Edge(int s, int e, int d) {
start = s;
end = e;
distance = d;
}
}
//优先级队列,实际中会用堆代替基于数组或链表的队列吧
class PQueue {
final int size;
int curSize;
Edge[] array;
public PQueue(int size) {
this.size = size;
curSize = 0;
array = new Edge[size];
}
// 从大到小
public void add(Edge e) {
int i;
for (i = 0; i < curSize; i++)
if (e.distance >= array[i].distance)
break;
for (int j = curSize - 1; j >= i; j--) {
array[j + 1] = array[j];
}
array[i] = e;
curSize++;
}
public Edge removeMin() {
return array[--curSize];
}
public void removeN(int n) {
for (int j = n; j < curSize - 1; j++)
array[j] = array[j + 1];
curSize--;
}
public int size() {
return curSize;
}
public Edge peekN(int n) {
return array[n];
}
public int find(int index) {
for (int j = 0; j < curSize; j++)
if (array[j].end == index)
return j;
return -1;
}
}
class Vertex {
char label;
boolean inTree;
public Vertex(char label) {
this.label = label;
inTree = false;
}
}
public class Graph {
private final int noEdge = -1;// 如果没有边,距离设置为-1
private final int maxVer;
private Vertex[] vertex;
private int[][] adjMat;
private int curVer;// 当前顶点index
private int nVers;// 当前顶点数
private int nTree;// 在树中的顶点数
private PQueue queue;
public Graph(int size) {
nTree = 0;
nVers = 0;
maxVer = size;
vertex = new Vertex[maxVer];
queue = new PQueue(maxVer);
adjMat = new int[maxVer][maxVer];
for (int i = 0; i < maxVer; i++)
for (int j = 0; j < maxVer; j++)
adjMat[i][j] = noEdge;// 初始值
}
public void addVer(char label) {
vertex[nVers++] = new Vertex(label);
}
// 假设无向
public void addEdge(int ver1, int ver2, int distance) {
if (ver1 == ver2)
return;
adjMat[ver1][ver2] = distance;
adjMat[ver2][ver1] = distance;
}
public void displayVer(int key) {
System.out.print(vertex[key].label);
}
public void mst() {
curVer = 0;// 这个起始点是任意的,0-5全试过
while (nTree < nVers - 1) {
vertex[curVer].inTree = true;
nTree++;
for (int j = 0; j < nVers; j++) {
if (j == curVer)// 排除自己
continue;
if (vertex[j].inTree)// 已经在队列中
continue;
int distance = adjMat[curVer][j];
if (distance == noEdge)// 如果2个顶点无边
continue;
putInQueue(j, distance);
}
if (queue.size() == 0) {
System.out.println("graph has not been connected");
return;
}
Edge edge = queue.removeMin();
int start = edge.start;
curVer = edge.end;
System.out.print(vertex[start].label);
System.out.print(vertex[curVer].label);
System.out.println();
}
for (int i = 0; i < nVers; i++) {
vertex[i].inTree = false;
}
}
private void putInQueue(int j, int distance) {
int index = queue.find(j);
if (index != -1) {
Edge edge = queue.peekN(index);
int oldDist = edge.distance;
// 如果队列里最大的距离大于添加的距离,就移除它,因为每次选最小距离
// 而如果要添加的距离大于等于它,则不予添加
if (oldDist > distance) {
queue.removeN(index);
Edge newEdge = new Edge(curVer, j, distance);
queue.add(newEdge);
}
} else {// 如果队列里没有以j为终点的边,直接添加
Edge edge = new Edge(curVer, j, distance);
queue.add(edge);
}
}
public static void main(String[] args) {
Graph g = new Graph(20);
g.addVer('A');
g.addVer('B');
g.addVer('C');
g.addVer('D');
g.addVer('E');
g.addVer('F');
g.addEdge(0, 1, 6);
g.addEdge(0, 3, 4);
g.addEdge(1, 2, 10);
g.addEdge(1, 3, 7);
g.addEdge(1, 4, 7);
g.addEdge(2, 3, 8);
g.addEdge(2, 4, 5);
g.addEdge(2, 5, 6);
g.addEdge(3, 4, 12);
g.addEdge(4, 5, 7);
g.mst();
}
}