带权图的最小生成树

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();
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值