package org.exam.ch14.mstw;
/**
* Created by xin on 15.10.21.
*/
class Edge {
public int srcVert; // index of a vertex starting edge
public int destVert; // index of a vertex ending edge
public int distance; // distance from src to dest
public Edge(int sv, int dv, int d) {
srcVert = sv;
destVert = dv;
distance = d;
}
}
class PriorityQ {
private Edge[] queArray;
private int size;
public PriorityQ() {
queArray = new Edge[20];
}
public void insert(Edge item) {// insert item in sorted order(插入法,降序)
int j;
for (j = 0; j < size; j++) { // find place to insert
if (item.distance >= queArray[j].distance) {
break;
}
}
for (int k = size - 1; k >= j; k--) { // move items up
queArray[k + 1] = queArray[k];
}
queArray[j] = item; // insert item
size++;
}
public Edge removeMin() {// remove minimum item
return queArray[--size];
}
public void removeN(int n) { // remove item at n
for (int j = n; j < size - 1; j++) { // move items down
queArray[j] = queArray[j + 1];
}
size--;
}
public Edge peekMin() {// peek at minimum item
return queArray[size - 1];
}
public int size() { // return number of items
return size;
}
public boolean isEmpty() { // true if queue is empty
return (size == 0);
}
public Edge peekN(int n) { // peek at item n
return queArray[n];
}
public int find(int findDex) { // find item with specified destVert value
for (int j = 0; j < size; j++) {
if (queArray[j].destVert == findDex) {
return j;
}
}
return -1;
}
}
class Vertex {
public char label; // label (e.g. 'A')
public boolean isInTree;//标记此顶点是否在生成的最小树中
public Vertex(char lab) { // constructor
label = lab;
isInTree = false;
}
}
class Graph {
private final int INFINITY = 1000000;
private Vertex vertexList[]; // list of vertices
private int adjMat[][]; // adjacency matrix
private int nVerts; // current number of vertices
private int currentVert;
private PriorityQ priorityQ; //存储到达该某个顶点的边(取权值最小者)
private int nTree;
public Graph() {// constructor
int MAX_VERTS = 20;
vertexList = new Vertex[MAX_VERTS];
// adjacency matrix
adjMat = new int[MAX_VERTS][MAX_VERTS];
for (int j = 0; j < MAX_VERTS; j++) { // set adjacency
for (int k = 0; k < MAX_VERTS; k++) { // matrix to 0
adjMat[j][k] = INFINITY;
}
}
priorityQ = new PriorityQ();
}
public void addVertex(char lab) {
vertexList[nVerts++] = new Vertex(lab);
}
public void addEdge(int start, int end, int weight) {
adjMat[start][end] = weight;
adjMat[end][start] = weight;
}
public void displayVertex(int v) {
System.out.print(vertexList[v].label);
}
public void mstw(){
currentVert=0;//最初选点
for (nTree=0;nTree<nVerts-1;nTree++){//while not all vertex in tree,put current vertex in tree
vertexList[currentVert].isInTree=true;
for (int j = 0; j < nVerts; j++) {//for each vertex
if (j==currentVert || vertexList[j].isInTree) {//如果是自己的话或将要放入的边已在队列当中,要跳过
continue;
}
int distance = adjMat[currentVert][j];//权值
if (distance == INFINITY) {//如果当前顶点到此顶点的权值是默认值,也跳过,因为看作是当前顶点与此顶点不相邻
continue;
}
puntInPQ(j, distance);//看方法注释
}
if (priorityQ.size()==0){
System.out.println("Graph not connected");
return;
}
Edge theEdge= priorityQ.removeMin();//将以当前顶点为起点,并且权值最小边从队列中移除
int sourceVert=theEdge.srcVert;
currentVert=theEdge.destVert;//作为下一个选点
displayVertex(sourceVert);
displayVertex(currentVert);
System.out.print(" ");
}
for (int j = 0; j < nVerts; j++) {
vertexList[j].isInTree=false;
}
}
/**
* 如果此边还没有插入队列,直接插入;否则,将插入队列对应的边与新边比较,将权值较小值插入队列
* @param newVert
* @param newDist
*/
private void puntInPQ(int newVert, int newDist) {
int queueIndex = priorityQ.find(newVert);//从优先级队列查看是否有到达newVert顶点的边
if (queueIndex != -1) {// 得到边在队列的索引
Edge tempEdge = priorityQ.peekN(queueIndex); //得到此边
int oldDist = tempEdge.distance; //得到权值
if (oldDist > newDist) { //如果新边权值更小
priorityQ.removeN(queueIndex); //从队列移除旧边
priorityQ.insert(new Edge(currentVert, newVert, newDist));//将新边插入队列
}//如果新边权值不小于旧边,不作处理
} else {//没有到达newVert顶点的边
priorityQ.insert(new Edge(currentVert, newVert, newDist));//直接插入新边
}
}
}
public class App {
public static void main(String[] args) {
Graph theGraph = new Graph();
theGraph.addVertex('A'); // 0 (start for mst)
theGraph.addVertex('B'); // 1
theGraph.addVertex('C'); // 2
theGraph.addVertex('D'); // 3
theGraph.addVertex('E'); // 4
theGraph.addVertex('F'); // 5
theGraph.addEdge(0, 1, 6); // AB 6
theGraph.addEdge(0, 3, 4); // AD 4
theGraph.addEdge(1, 2, 10); // BC 10
theGraph.addEdge(1, 3, 7); // BD 7
theGraph.addEdge(1, 4, 7); // BE 7
theGraph.addEdge(2, 3, 8); // CD 8
theGraph.addEdge(2, 4, 5); // CE 5
theGraph.addEdge(2, 5, 6); // CF 6
theGraph.addEdge(3, 4, 12); // DE 12
theGraph.addEdge(4, 5, 7); // EF 7
System.out.print("Minimum spanning tree: ");
theGraph.mstw(); // minimum spanning tree
System.out.println();
}
}
带权图的最小生成树
最新推荐文章于 2022-08-29 17:39:24 发布