/*
* 无向图的带权图最小生成树
*
* 如果终点已经在树中,则不能添加边
* 当终点在队列中但是不在树中时才能与新添加的边比较
*
* mstw():先判断三个条件,三个条件都不满足就将边putInQ,
* 放进去之后,再从队列中弹出一个权值最小的边边,将末尾的结
* 点作为下一个起始结点,打印弹出的边边的起始顶点来表示边边。
*
* putInQ():如果队列中已经存在了与要放进去的边边的终点相同
* 的边边,把要放进队列的边边与已经放进去的边边的权值进行比较。
* 将终点输入进Q.find()进行查找,返回索引值,然后根据索引值
* 找到oldDist,与newDist进行比较。
*
* 优先级队列的插入操作不熟悉!!!!!!!!!!!!!!!!!!!!!!!!!
*/
package graph;
/*
* 无向图的带权图最小生成树
*
* 如果终点已经在树中,则不能添加边
* 当终点在队列中但是不在树中时才能与新添加的边比较
*
* mstw():先判断三个条件,三个条件都不满足就将边putInQ,
* 放进去之后,再从队列中弹出一个权值最小的边边,将末尾的结
* 点作为下一个起始结点,打印弹出的边边的起始顶点来表示边边。
*
* putInQ():如果队列中已经存在了与要放进去的边边的终点相同
* 的边边,把要放进队列的边边与已经放进去的边边的权值进行比较。
* 将终点输入进Q.find()进行查找,返回索引值,然后根据索引值
* 找到oldDist,与newDist进行比较。
*
* 优先级队列的插入操作不熟悉!!!!!!!!!!!!!!!!!!!!!!!!!
*/
class Edge{
int startVert;
int destVert;
int distance;
public Edge(int sv, int dv, int d) {
startVert = sv;
destVert = dv;
distance = d;
}
}
class PriorityQ{
int MAX_SIZE;
Edge[] prioQueue;
int nitems;
public PriorityQ(int size) {
MAX_SIZE = size;
prioQueue = new Edge[MAX_SIZE];
nitems = 0;
}
public int find(int dest) {
for(int i=0; i<nitems; i++) {
if(prioQueue[i].destVert == dest) {
return i;
}
}
return -1;
}
//优先级队列的插入
public void insert(Edge e) {
int j;
if(nitems == 0) {
prioQueue[nitems] = e;
}
//j--
for(j=nitems-1; j>=0; j--) {
if(e.distance > prioQueue[j].distance) {
prioQueue[j+1] = prioQueue[j];
}else
{
break;
}
}
prioQueue[j+1] = e;
nitems++;
}
public Edge remove() {
return prioQueue[--nitems];
}
//有新的权值的话,删除旧的权值
public void removeN(int n) {
for(int i=n; i<nitems; i++) {
prioQueue[i] = prioQueue[i+1];
}
nitems--;
}
public Edge peekMin() {
return prioQueue[nitems-1];
}
//获取旧的权值的时候,方便访问
public Edge peekN(int n) {
return prioQueue[n];
}
public boolean isEmpty() {
return nitems == 0;
}
public boolean isFull() {
return nitems == MAX_SIZE;
}
public int size() {
return nitems;
}
}
class vert{
char label;
boolean isInTree;
public vert(char lab) {
label = lab;
isInTree = false;
}
}
public class mstwGraph {
int MAX_SIZE;
vert[] VertList;
int nVerts;
int INF = 10000;
int[][] adjMat;
int size = 15;
PriorityQ Q;
public mstwGraph(int size) {
MAX_SIZE = size;
VertList = new vert[MAX_SIZE];
nVerts = 0;
size = 15;
Q= new PriorityQ(size);
adjMat = new int[MAX_SIZE][MAX_SIZE];
for(int i=0; i<MAX_SIZE; i++) {
for(int j=0; j<MAX_SIZE; j++) {
adjMat[i][j] = INF;
}
}
}
public void addVerts(char lab) {
vert v = new vert(lab);
VertList[nVerts++] = v;
}
public void addEdge(int startVert, int destVert, int distance) {
adjMat[startVert][destVert] = distance;
adjMat[destVert][startVert] = distance;
}
public void mstw() {
int currentVert = 0;
int nInTrees = 1;
while(nInTrees < nVerts) {
VertList[currentVert].isInTree = true;
nInTrees++;
for(int i=0; i<nVerts; i++) {
int distance = adjMat[currentVert][i];
if(distance == INF) {
continue;
}
if(VertList[i].isInTree) {
continue;
}
if(i==currentVert) {
continue;
}
putInQ(currentVert, i, distance);
}
if(Q.size() == 0) {
System.out.println("The graph is not conneted!");
return;
}
Edge eMin = Q.remove();
int srcVert = eMin.startVert;
currentVert = eMin.destVert;
System.out.print(VertList[srcVert].label);
System.out.print(VertList[currentVert].label+" ");
}
for(int i=0; i<nVerts; i++) {
VertList[i].isInTree = false;
}
}
public void putInQ(int curVert, int oldVert, int newDist) {
int queueIndex = Q.find(oldVert);
if(queueIndex != -1) {
int oldDist = Q.peekN(queueIndex).distance;
if(oldDist>newDist) {
Q.removeN(queueIndex);
Edge e = new Edge(curVert, oldVert, newDist);
Q.insert(e);
}
}
//如果既有相同终点,又权值大,就不进行插入操作了
else
{
Edge e = new Edge(curVert, oldVert, newDist);
Q.insert(e);
}
}
public static void main(String[] args) {
mstwGraph g = new mstwGraph(20);
g.addVerts('A');
g.addVerts('B');
g.addVerts('C');
g.addVerts('D');
g.addVerts('E');
//g.addVerts('F');
g.addEdge(0, 1, 1);
g.addEdge(0, 2, 2);
g.addEdge(0, 4, 5);
g.addEdge(1, 3, 4);
g.addEdge(2, 3, 3);
//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.mstw();
}
}