图【数据结构与算法java】

简介: 图【数据结构与算法java】

StackX

package dfs;
/**
 * @author CSDN@日星月云
 * @date 2022/10/26 19:03
 */
public class StackX {
    private final int SIZE = 20;
    private int[] st;
    private int top;
    public StackX() {// constructor
        st = new int[SIZE];
        top = -1;// make array
    }
    public void push(int j) { // put item on stack
        st[++top] = j;
    }
    public int pop() {// take item off stack
        return st[top--];
    }
    public int peek() {// peek at top of stack
        return st[top];
    }
    public boolean isEmpty() { // true if nothing on stack
        return (top == -1);
    }
    //测试StackX
    public static void main(String[] args) {
        StackX stackX=new StackX();
        System.out.println(stackX.isEmpty());
        stackX.push(1);
        stackX.push(2);
        stackX.push(3);
        stackX.pop();
        int peek = stackX.peek();
        System.out.println(peek);
        stackX.pop();
        stackX.pop();
        System.out.println(stackX.isEmpty());
    }
}  // end class Stackx

QueueX

package bfs;
/**
 * @author CSDN@日星月云
 * @date 2022/10/26 19:10
 */
public class QueueX {
    private final int SIZE = 20;
    private int[] queArray;
    private int front;
    private int rear;
    public QueueX() {// constructor
        queArray = new int[SIZE];
        front = 0;
        rear = -1;
    }
    public void insert(int j) {// put item at rear of queue
        if (rear == SIZE - 1)
            rear = -1;
        queArray[++rear] = j;
    }
    public int remove() {// take item from front of queue
        int temp = queArray[front++];
        if (front == SIZE)
            front = 0;
        return temp;
    }
    public boolean isEmpty() {// true if queue is empty
        return (rear + 1 == front || (front + SIZE - 1 == rear));
    }
    //测试Queue
    public static void main(String[] args) {
        QueueX queueX =new QueueX();
        System.out.println(queueX.isEmpty());
        queueX.insert(1);
        queueX.insert(2);
        queueX.insert(3);
        int remove = queueX.remove();
        System.out.println(remove);
        queueX.remove();
        queueX.remove();
        System.out.println(queueX.isEmpty());
    }
} // end class QueueX

dfs

DFSApp

package dfs;
/**
 * @author CSDN@日星月云
 * @date 2022/10/26 18:37
 * bfs
 * 深度优先搜索
 * 规则1如果可能,访问一个邻接的未访问顶点,标记它,并把它放入栈中。
 * 规则2当不能执行规则1时,如果栈不空,就从栈中弹出一个顶点。
 * 规则3如果不能执行规则1和规则2,就完成了整个搜索过程。
 */
class Vertex {
    public char label;// label (e.g. 'A')
    public boolean wasVisited;
    public Vertex(char lab){// constructor
        label = lab;
        wasVisited = false;
    }
}
class Graph {
    private final int MAX_VERTS = 20;
    private Vertex vertexList[]; // array of vertices
    private int adjMat[][];     // adjacency matrix
    private int nVerts;         // current number of vertices
    private StackX theStack;
    //------------------------------------------------------------
    public Graph() { // constructor
        vertexList = new Vertex[MAX_VERTS];// adjacency matrix
        adjMat = new int[MAX_VERTS][MAX_VERTS];
        nVerts = 0;
        for (int j = 0; j < MAX_VERTS; j++)// set adjacency
            for (int k = 0; k < MAX_VERTS; k++)//matrix to 0
                adjMat[j][k] = 0;
        theStack = new StackX();
    }// end constructor
    //------------------------------------------------------------
    public void addVertex(char lab) {// argument is label
        vertexList[nVerts++] = new Vertex(lab);
    }
    //------------------------------------------------------------
    public void addEdge(int start, int end) {
        adjMat[start][end] = 1;
        adjMat[end][start] = 1;
    }
    public void displayVertex(int v) {
        System.out.print(vertexList[v].label);
    }
    //------------------------------------------------------------
    /**
     * 深度优先搜索的关键在于能够找到与某一顶点邻接且没有访问过的顶点。如何做呢?邻接矩阵
     * 是关键。找到指定顶点所在的行,从第一列开始向后寻找值为1的列:列号是邻接顶点的号码。检
     * 查这个顶点是否未访问过,如果是这样,那么这就是要访问的下一个顶点。如果该行没有顶点既等
     * 于1 (邻接)且又是未访问的,那么与指定点相邻接的顶点就全部访问过了。这个过程在
     * getAdjUnvisitedVertex ()方法中实现:
     */
    // returns an unvisited vertex adjacent to v
    public int getAdjUnvisitedVertex(int v) {
        for (int j = 0; j < nVerts; j++)
            if (adjMat[v][j] == 1 && vertexList[j].wasVisited == false)
                return j;// return first such vertex
        return -1;// no such vertices
    } // end getAdjUnvisitedVertex()
    /**
     * 现在开始考察Graph类中的dfs()方法,这个方法实际执行了深度优先搜索。下面会看到这段代
     * 码如何包含了前面提出的三条规则。它循环执行,直到栈为空。每次循环中,它做四件书:
     * 1.用peek()方法检查栈顶的顶点。
     * 2.试图找到这个顶点还未访问的邻接点。
     * 3.如果没有找到,出栈。
     * 4.如果找到这样的顶点,访问这个顶点,并把它放入栈。
     * 5.下面是dfs()方法的代码:
     */
    public void dfs() { // depth-first search
//        Stack<Integer> theStack = new Stack<>();//java.util.Stack
        // begin at vertex 0
        vertexList[0].wasVisited = true;// mark it
        displayVertex(0);//display it
        theStack.push(0);// push it
        while (!theStack.isEmpty()) {// until stack empty,
            // get an unvisited vertex adjacent to stack top
            int v = getAdjUnvisitedVertex(theStack.peek());
            if (v == -1)// if no such vertex,
                theStack.pop();//pop a new one
            else {// if it exists,
                vertexList[v].wasVisited = true;  // mark it
                displayVertex(v); // display it
                theStack.push(v);// push it
            }
        } // end while
        // stack is empty, so we're done
        for (int j = 0; j < nVerts; j++)// reset flags
            vertexList[j].wasVisited = false;
    }// end dfs
    /**
     * 在dfs()方法的最后,重置了所有wasVisited标记位,这样就可以在稍后继续使用dfs()方法。栈
     * 此时已为空,所以不需要重置。
     */
}// end class Graph
class DFSApp{
    /**
     * 现在Graph类已经有了需要的所有片段.下面是创建图对象的代码,并在图中加入一些顶点和
     * 边,然后执行深度优先搜索
     */
    public static void main(String[] args) {
        Graph theGraph = new Graph();
        theGraph.addVertex('A');//0 (start for dfs)
        theGraph.addVertex('B');//1
        theGraph.addVertex('C');//2
        theGraph.addVertex('D');//3
        theGraph.addVertex('E');//4
        theGraph.addEdge(0, 1);// AB
        theGraph.addEdge(1, 2);// BC
        theGraph.addEdge(0, 3);// AD
        theGraph.addEdge(3, 4);// DE
        /*
        A--B--C
        |
        D--E
         */
        System.out.print("Visits:");
        theGraph.dfs();       // depth-first search
        System.out.println();//Visits:ABCDE
    }
}

bfs

BFSApp

package bfs;
/**
 * @author CSDN@日星月云
 * @date 2022/10/26 18:37
 * bfs
 * 广度优先搜索
 * 规则1访问下一个未来访问的邻接点(如果存在),这个顶点必须是当前顶点的邻接点,标记它,并把它插入到队列中。
 * 规则2如果因为已经没有未访问顶点而不能执行规则1,那么从队列头取一个顶点(如果存在),并使其成为当前顶点。
 * 规则3如果因为队列为空而不能执行规则2,则搜索结束。
 */
class Vertex {
    public char label;// label (e.g. 'A')
    public boolean wasVisited;
    public Vertex(char lab){// constructor
        label = lab;
        wasVisited = false;
    }
}
class Graph {
    private final int MAX_VERTS = 20;
    private Vertex vertexList[]; // array of vertices
    private int adjMat[][];     // adjacency matrix
    private int nVerts;         // current number of vertices
    private QueueX theQueueX;
    //------------------------------------------------------------
    public Graph() { // constructor
        vertexList = new Vertex[MAX_VERTS];// adjacency matrix
        adjMat = new int[MAX_VERTS][MAX_VERTS];
        nVerts = 0;
        for (int j = 0; j < MAX_VERTS; j++)// set adjacency
            for (int k = 0; k < MAX_VERTS; k++)//matrix to 0
                adjMat[j][k] = 0;
        theQueueX = new QueueX();
    }// end constructor
    //------------------------------------------------------------
    public void addVertex(char lab) {// argument is label
        vertexList[nVerts++] = new Vertex(lab);
    }
    //------------------------------------------------------------
    public void addEdge(int start, int end) {
        adjMat[start][end] = 1;
        adjMat[end][start] = 1;
    }
    public void displayVertex(int v) {
        System.out.print(vertexList[v].label);
    }
    //------------------------------------------------------------
    // returns an unvisited vertex adjacent to v
    public int getAdjUnvisitedVertex(int v) {
        for (int j = 0; j < nVerts; j++)
            if (adjMat[v][j] == 1 && vertexList[j].wasVisited == false)
                return j;// return first such vertex
        return -1;// no such vertices
    } // end getAdjUnvisitedVertex()
    public void bfs() {// breadth-first search
//        Queue<Integer> theQueue=new ArrayDeque<>();//java.util.Queue
        // begin at vertex 0
        vertexList[0].wasVisited = true; // mark it
        displayVertex(0);// display it
        theQueueX.insert(0); // insert at tail
        int v2;
        while (!theQueueX.isEmpty()) {// until queue empty,
            int v1 = theQueueX.remove();// remove vertex at head
            // until it has no unvisited neighbors
            while ((v2 = getAdjUnvisitedVertex(v1)) != -1) {// get one,
                vertexList[v2].wasVisited = true;// mark it
                displayVertex(v2);// display it
                theQueueX.insert(v2);// insert it
            } // end while
        }// end while(queue not empty)
        // queue is empty, so we're done
        for (int j = 0; j < nVerts; j++) {
            vertexList[j].wasVisited = false; // reset flags
        }
    }// end bfs()
}// end class Graph
public class BFSApp{
    //测试  bfs
    public static void main(String[] args) {
        Graph theGraph = new Graph();
        theGraph.addVertex('A');//0 (start for dfs)
        theGraph.addVertex('B');//1
        theGraph.addVertex('C');//2
        theGraph.addVertex('D');//3
        theGraph.addVertex('E');//4
        theGraph.addEdge(0, 1);// AB
        theGraph.addEdge(1, 2);// BC
        theGraph.addEdge(0, 3);// AD
        theGraph.addEdge(3, 4);// DE
        /*
        A--B--C
        |
        D--E
         */
        System.out.print("Visits:");
        theGraph.bfs();// breadth-first search
        System.out.println();//Visits:ABDCE
    }
}

mst

MSTApp

package mst;
/**
 * @author CSDN@日星月云
 * @date 2022/10/26 18:37
 * mst
 * 最小生成树
 */
class Vertex {
    public char label;// label (e.g. 'A')
    public boolean wasVisited;
    public Vertex(char lab){// constructor
        label = lab;
        wasVisited = false;
    }
}
class Graph {
    private final int MAX_VERTS = 20;
    private Vertex vertexList[]; // array of vertices
    private int adjMat[][];     // adjacency matrix
    private int nVerts;         // current number of vertices
    private StackX theStack;
    //------------------------------------------------------------
    public Graph() { // constructor
        vertexList = new Vertex[MAX_VERTS];// adjacency matrix
        adjMat = new int[MAX_VERTS][MAX_VERTS];
        nVerts = 0;
        for (int j = 0; j < MAX_VERTS; j++)// set adjacency
            for (int k = 0; k < MAX_VERTS; k++)//matrix to 0
                adjMat[j][k] = 0;
        theStack = new StackX();
    }// end constructor
    //------------------------------------------------------------
    public void addVertex(char lab) {// argument is label
        vertexList[nVerts++] = new Vertex(lab);
    }
    //------------------------------------------------------------
    public void addEdge(int start, int end) {
        adjMat[start][end] = 1;
        adjMat[end][start] = 1;
    }
    public void displayVertex(int v) {
        System.out.print(vertexList[v].label);
    }
    //------------------------------------------------------------
    // returns an unvisited vertex adjacent to v
    public int getAdjUnvisitedVertex(int v) {
        for (int j = 0; j < nVerts; j++)
            if (adjMat[v][j] == 1 && vertexList[j].wasVisited == false)
                return j;// return first such vertex
        return -1;// no such vertices
    } // end getAdjUnvisitedVertex()
    //最小生成树
    public void mst() {// minimum spanning tree (depth first)
        // start at 0
        vertexList[0].wasVisited = true;// mark it
        theStack.push(0);// push it
        while (!theStack.isEmpty()) {// until stack empty
            // get stack top
            int currentVertex = theStack.peek();
            //get next unvisited neighbor
            int v = getAdjUnvisitedVertex(currentVertex);
            if (v == -1) {
                // if no more neighbors
                theStack.pop();// pop it away
            } else { // got a neighbor
                vertexList[v].wasVisited = true; // mark it
                theStack.push(v);// push it
                // display edge
                displayVertex(currentVertex);// from currentV
                displayVertex(v);// to v
                System.out.print(" ");
            }
        }// end while(stack not empty)
        // stack is empty, so we're done
        for (int j = 0; j < nVerts; j++) {// reset flags
            vertexList[j].wasVisited = false;
        } // end tree
    }
}// end class Graph
public class MSTApp{
    //测试 mst
    public static void main(String[] args) {
        Graph theGraph = new Graph();
        theGraph.addVertex('A');//0 (start for dfs)
        theGraph.addVertex('B');//1
        theGraph.addVertex('C');//2
        theGraph.addVertex('D');//3
        theGraph.addVertex('E');//4
        theGraph.addEdge(0, 1);// AB
        theGraph.addEdge(0, 2);// AC
        theGraph.addEdge(0, 3);// AD
        theGraph.addEdge(0, 4);// AE
        theGraph.addEdge(1, 2);// BC
        theGraph.addEdge(1, 3);// BD
        theGraph.addEdge(1, 4);// BD
        theGraph.addEdge(2, 3);// CD
        theGraph.addEdge(2, 4);// CE
        theGraph.addEdge(3, 4);// DE
        /*
        A--B--C
        |
        D--E
         */
        System.out.print("Minimum spanning tree:");
        theGraph.mst();       // minimum spanning tree
        System.out.println(); // AB BC CD DE
    }
}

topo

TopoApp

package topo;
/**
 * @author CSDN@日星月云
 * @date 2022/10/26 18:37
 * 有向图
 * topo
 * 拓扑排序
 * 步骤1找到一个没有后继的顶点。
 * 步骤2从图中删除这个顶点,在列表的前面插入顶点的标记。
 * 重复步骤1和步骤2,直到所有顶点都从图中删除。
 * 这时,列表显示的顶点顺序就是拓扑排序的结果。
 */
class Vertex {
    public char label;// label (e.g. 'A')
    public boolean wasVisited;
    public Vertex(char lab) {// constructor
        label = lab;
        wasVisited = false;
    }
}
class Graph {
    private final int MAX_VERTS = 20;
    private Vertex vertexList[]; // array of vertices
    private int adjMat[][];     // adjacency matrix
    private int nVerts;         // current number of vertices
    private char[] sortedArray;
    //------------------------------------------------------------
    public Graph() { // constructor
        vertexList = new Vertex[MAX_VERTS];// adjacency matrix
        adjMat = new int[MAX_VERTS][MAX_VERTS];
        nVerts = 0;
        for (int j = 0; j < MAX_VERTS; j++)// set adjacency
            for (int k = 0; k < MAX_VERTS; k++)//matrix to 0
                adjMat[j][k] = 0;
        sortedArray = new char[MAX_VERTS];// sorted vert labels
    }// end constructor
    //------------------------------------------------------------
    public void addVertex(char lab) {// argument is label
        vertexList[nVerts++] = new Vertex(lab);
    }
    //------------------------------------------------------------
    public void addEdge(int start, int end) {
        adjMat[start][end] = 1;
    }
    public void displayVertex(int v) {
        System.out.print(vertexList[v].label);
    }
    //------------------------------------------------------------
    public void topo() {// topological sort
        int orig_nVerts = nVerts; // remember how many verts
        while (nVerts > 0) { // while vertices remain,
            // get a vertex with no successors, or -1
            int currentVertex = noSuccessors();
            if (currentVertex == -1) {// must be a cycle
                System.out.println("ERROR: Graph has cycles");
                return;
            }
            // insert vertex label in sorted array (start at end)
            sortedArray[nVerts - 1] = vertexList[currentVertex].label;
            deleteVertex(currentVertex); // delete vertex}
        }// end while
        // vertices all gone;display sortedArray
        System.out.print("Topologically sorted order: ");
        for (int j = 0; j < orig_nVerts; j++) {
            System.out.print(sortedArray[j]);
        }
        System.out.println("");
    }// end topo
    /**
     *主要工作在while循环中进行。这个循环直到顶点数目为0时才退出。下面是步骤:
     * 1.调用noSuccessors()找到任意一个没有后继的顶点。
     * 2.如果找到一个这样的顶点,把顶点放入数组sortedArray[],并且从图中删除顶点。
     * 3.如果没有这样的顶点,则图必然存在环。
     *
     * 最后一个被删除的顶点出现在列表的开头,所以,随着nVerts (图中顶点个数)逐渐变小,顶
     * 点从sortedArray数组的最后开始,依次向前排列。
     *
     * 如果有顶点还在图中,但它们都有后继,那么图必然存在环,算法会显示一条信息并退出。如
     * 果没有环,则while循环退出,显示sortedArray数组中的数据,这时顶点是按拓扑有序排列。
     *
     */
    /**
     * noSuccessorsO方法使用邻接矩阵找到没有后继的顶点。在外层for循环中,沿着每一行考察每
     * 个顶点。在每行中,用内层for循环扫描列,査找值为1的顶点。如果找到一个,就说明顶点有后
     * 继,因为从这个顶点到其他点有边存在。当找到一个1时,跳出内层循环,考察下一个顶点。
     * <p>
     * 只有整个一行都没有1存在,才说明有一个顶点没有后继;这时,就返回它的行号。如果没有
     * 这样的顶点,就返回-1。下面是noSuccessors()方法:
     */
    public int noSuccessors() {// returns vert with no successors
        // (or -1 if no such verts)
        boolean isEdge; // edge from row to column in adjMat
        for (int row = 0; row < nVerts; row++) { // for each vertex,
            isEdge = false;
            for (int col = 0; col < nVerts; col++) { // check edges
                if (adjMat[row][col] > 0) { // if edge to
                    // another,
                    isEdge = true;             // this vertex
                    break;
                }//has a successor
            }// try another
            if (!isEdge)// if no edges,
                return row;  // has no successor
        }
        return -1;// no such vertex
    }// end noSuccessors()
    /**
     * 除了一些细节外,删除一个顶点很简单。顶点从vertexList[]数组删除,后面的顶点向前移动填
     * 补空位。同样的,顶点的行列从邻接矩阵中删除,下面的行和右面的列移动来填补空位。这些任务
     * 由delete Vertex。、moveRowUp()和moveColLeft ()方法来完成。这些方法将在topo.java程序的完整
     * 代码(清单13.4)中看到。对于这个算法,用邻接表表示图效率更高,但要使用更多空间。
     */
    public void deleteVertex(int delVert) {
        if (delVert != nVerts - 1) {// if not last vertex,
            // delete from vertexList
            for (int j = delVert; j < nVerts - 1; j++)
                vertexList[j] = vertexList[j + 1];
            // delete row from adjMat
            for (int row = delVert; row < nVerts - 1; row++)
                moveRowUp(row, nVerts);
            // delete col from adjMat
            for (int col = delVert; col < nVerts - 1; col++)
                moveColLeft(col, nVerts - 1);
        }
        nVerts--;// one less vertex
    }// end deleteVertex
    private void moveRowUp(int row, int length) {
        for (int col = 8; col < length; col++) {
            adjMat[row][col] = adjMat[row + 1][col];
        }
    }
    private void moveColLeft(int col, int length) {
        for (int row = 0; row < length; row++)
            adjMat[row][col] = adjMat[row][col + 1];
    }
}// end class Graph
public class TopoApp {
    /**
     * main。例程调用一些方法创建如图13.10所示的图,这些方法与前面看到的类似。应该注意到,
     * addEdge()方法只在邻接矩阵中插入一个数,因为这是有向图。下面是main()方法的代码:
     */
    public static void main(String[] args) {
        Graph theGraph = new Graph();
        theGraph.addVertex('A');//0
        theGraph.addVertex('B');//1
        theGraph.addVertex('C');//2
        theGraph.addVertex('D');//3
        theGraph.addVertex('E');//4
        theGraph.addVertex('F');//5
        theGraph.addVertex('G');//6
        theGraph.addVertex('H');//7
        theGraph.addEdge(0, 3);// AD
        theGraph.addEdge(0, 4);// AE
        theGraph.addEdge(1, 4);// BE
        theGraph.addEdge(2, 5);// CF
        theGraph.addEdge(3, 6);// DG
        theGraph.addEdge(4, 6);// EG
        theGraph.addEdge(5, 7);// FH
        theGraph.addEdge(6, 7);// GH
        theGraph.topo();// do the sort
        /*
        Topologically sorted order: GBAEDCFH
         */
    }// end main()
}// end class TopoApp

pstw

MSTWApp

package pstw;
/**
 * @author CSDN@日星月云
 * @date 2022/10/27 15:09
 *
 * 最小生成树
 * 无向带权图
 * 从一个顶点开始,把它放入树的集合中。然后重复做下面的事情:
 * 1.找到从最新的顶点到其他顶点的所有边,这些顶点不能在树的集合中。把这些边放入优先级队列。
 * 2.找岀权值最小的边,把它和它所到达的顶点放入树的集合中。
 * 重复这些步骤,直到所有顶点都在树的集合中。这时,工作完成。
 */
/**
 * PriorityQ类用数组存储对象。正如前面提到的,在处理大量数据的程序中,用堆存储对象比数
 * 组更合适。PriorityQ类已经增加了不同的方法,如前所示,它用find()方法找到到达指定顶点的边;
 * 用peekN()方法得到任意一个数据项;用removeN()方法删除任意一个数据项。程序的其余部分前面
 * 已经看到。清单14.1显示了完整的mstw.java程序。
 */
//mstw.java
// demonstrates minimum spanning tree with weighted graphs
// to run this program: C>java MSTWApp
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) // constructor
    {
        srcVert = sv;
        destVert = dv;
        distance = d;
    }
//
}// end class Edge
class PriorityQ {
    // array in sorted order, from max at 0 to min at size-1
    private final int SIZE = 20;
    private Edge[] queArray;
    private int size;
    //-------------------------------------------
    public PriorityQ() {    // constructor
        queArray = new Edge[SIZE];
        size = 0;
    }
    //
    public void insert(Edge item) {//If 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;
    }
}//end class PriorityQ
class Vertex {
    〃// class Vertex
    public char label; // label (e.g. 'A1)
    public boolean isInTree;
    //
    public Vertex(char lab) { // constructor
        label = lab;
        isInTree = false;
    }
//
} // end class Vertex
class Graph {
    private final int MAX_VERTS = 20;
    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 thePQ;
    private int nTree; // number of verts in tree
    public Graph()    // constructor
    {
        vertexList = new Vertex[MAX_VERTS];
        // adjacency matrix
        adjMat = new int[MAX_VERTS][MAX_VERTS];
        nVerts = 0;
        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;
        thePQ = new PriorityQ();
    }//end constructor
    //
    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);
    }
    /**
     * 根据前面的算法要点,编制有向图最小生成树的方法mstw()。正如其他图的程序一样,假定在
     * vertexList[]数组中有一个顶点列表,并且从下标为0的顶点开始。currentVert代表最近加到树中的
     * 顶点。下面是mstw()方法的代码:
     */
    public void mstw()    //  minimum spanning tree
    {
        currentVert = 0;    //  start at 0
        while (nTree < nVerts - 1) {    //  while not all verts in tree
            //  put currentVert in tree
            vertexList[currentVert].isInTree = true;
            nTree++;
            // insert edges adjacent to currentVert into PQ
            for (int j = 0; j < nVerts; j++) {// for each vertex,
                if (j == currentVert)// skip if it 's us
                    continue;
                if (vertexList[j].isInTree) // skip if in the tree
                    continue;
                int distance = adjMat[currentVert][j];
                if (distance == INFINITY)
                    continue;
                putInPQ(j, distance);//put it in PQ (maybe)
            }
            if (thePQ.size() == 0) {//no vertices in PQ?
                System.out.println("GRAPH NOT CONNECTED");
                return;
            }
            // remove edge with minimum distance, from PQ
            Edge theEdge = thePQ.removeMin();
            int sourceVert = theEdge.srcVert;
            currentVert = theEdge.destVert;
            // display edge from source to current
            System.out.print(vertexList[sourceVert].label);
            System.out.print(vertexList[currentVert].label);
            System.out.print(" ");
        }// end while( not all verts in tree)
        // mst is complete
        for (int j = 0; j < nVerts; j++)    // unmark vertices
            vertexList[j].isInTree = false;
    } // end mstw
    /**
     * 算法在while循环中执行,循环结束条件是所有顶点都己在树中。循环中完成下面的操作:
     * 1.当前顶点放在树中。
     * 2.连接这个顶点的边放到优先级队列中(如果合适)。
     * 3.从优先级队列中删除权值最小的边。这条边的目的顶点变成当前顶点。
     * 再看看这些步骤的细节。在步骤1中,通过标记currentVert所指顶点的isInTree字段来表示该
     * 顶点放入树中。
     * 在步骤2中,连接这个顶点的边插入优先级队列。通过在邻接矩阵中扫描行号是currentVert的
     * 行寻找需要的边。只要下面任意一个条件为真,这条边就不能放入队列中:
     *  •源点和终点相同。
     *  •终点在树中。
     *  •源点和终点之间没有边(邻接矩阵中对应的值等于无限大)。
     * 如果没有一个条件为真,调用putlnPQO方法把这条边放入队列中。实际上,正如下面要看到
     * 的,这个例程并不总把边放到队列中。
     * 在步骤3中,将最小权值的边从优先级队列中删除。把这条边和该边的终点加入树,并显示源
     * 点(currentVert)和终点。
     *在mstw()方法最后,所有顶点的isInTree变量被重置,即从树中删除。在该程序中这样做,是
     * 因为根据这些数据只能创建一棵树。然而,在完成一项工作后,最好把数据恢复到原始的形态。
     */
    /**
     * 正如前面所强调的,在优先级队列中应该只含有一条到达某个特定目标顶点的边。putlnPQ()
     * 方法保证了这一点。它调用PriorityQ类的find()方法,这个方法经过修正,可以寻找到达指定点的
     * 边。如果不存在到达指定点的边,find。方法返回一1,这时putlnPQ()方法只要把新边插入优先级队
     * 列中即可。然而,如果有到达指定点的老边存在,putlnPQ()方法就要检査老边是否比新边有更小的
     * 权值。如果老边的权值小,就不需要作什么变化。如果新边有更小的权值,就要把老边从队列中删
     * 除,把新边放进去。下面是putlnPQO方法的代码:
     */
    public void putInPQ(int newVert, int newDist) {
        //is there another edge with the same destination vertex?
        int queueIndex = thePQ.find(newVert);
        if (queueIndex != -1) {    // got edge's index
            Edge tempEdge = thePQ.peekN(queueIndex);// get edge
            int oldDist = tempEdge.distance;
            if (oldDist > newDist) {    // if new edge shorter,
                thePQ.removeN(queueIndex); // remove old edge
                Edge theEdge = new Edge(currentVert, newVert, newDist);
                thePQ.insert(theEdge);    // insert new edge
            }
            // else no action; just leave the old vertex there
        } // end if
        else { //no edge with same destination vertex
            //so insert new one
            Edge theEdge = new Edge(currentVert, newVert, newDist);
            thePQ.insert(theEdge);
        }
    } // end putInPQ()
} // end class Graph
class MSTWApp {
    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();//Minimum spanning tree: AD AB BE EC CF
    }// end main()
}//end class MSTWApp
///
相关文章
|
2月前
|
存储 人工智能 算法
数据结构与算法细节篇之最短路径问题:Dijkstra和Floyd算法详细描述,java语言实现。
这篇文章详细介绍了Dijkstra和Floyd算法,这两种算法分别用于解决单源和多源最短路径问题,并且提供了Java语言的实现代码。
92 3
数据结构与算法细节篇之最短路径问题:Dijkstra和Floyd算法详细描述,java语言实现。
|
2月前
|
存储 Java
数据结构第二篇【关于java线性表(顺序表)的基本操作】
数据结构第二篇【关于java线性表(顺序表)的基本操作】
40 6
|
2月前
|
算法 Java 数据中心
探讨面试常见问题雪花算法、时钟回拨问题,java中优雅的实现方式
【10月更文挑战第2天】在大数据量系统中,分布式ID生成是一个关键问题。为了保证在分布式环境下生成的ID唯一、有序且高效,业界提出了多种解决方案,其中雪花算法(Snowflake Algorithm)是一种广泛应用的分布式ID生成算法。本文将详细介绍雪花算法的原理、实现及其处理时钟回拨问题的方法,并提供Java代码示例。
92 2
|
2月前
|
算法 Java 测试技术
数据结构 —— Java自定义代码实现顺序表,包含测试用例以及ArrayList的使用以及相关算法题
文章详细介绍了如何用Java自定义实现一个顺序表类,包括插入、删除、获取数据元素、求数据个数等功能,并对顺序表进行了测试,最后还提及了Java中自带的顺序表实现类ArrayList。
32 0
|
4月前
|
算法 Java
LeetCode经典算法题:矩阵中省份数量经典题目+三角形最大周长java多种解法详解
LeetCode经典算法题:矩阵中省份数量经典题目+三角形最大周长java多种解法详解
57 6
|
4月前
|
搜索推荐 算法 Java
|
4月前
|
搜索推荐 算法 Java
经典排序算法之-----选择排序(Java实现)
这篇文章通过Java代码示例详细解释了选择排序算法的实现过程,包括算法的基本思想、核心代码、辅助函数以及测试结果,展示了如何通过选择排序对数组进行升序排列。
经典排序算法之-----选择排序(Java实现)
|
4月前
|
存储 Java
数据结构中的哈希表(java实现)利用哈希表实现学生信息的存储
这篇文章通过Java代码示例展示了如何实现哈希表,包括定义结点类、链表类、数组存储多条链表,并使用简单的散列函数处理冲突,以及如何利用哈希表存储和查询学生信息。
数据结构中的哈希表(java实现)利用哈希表实现学生信息的存储
|
4月前
|
存储 算法 Java
LeetCode经典算法题:打家劫舍java详解
LeetCode经典算法题:打家劫舍java详解
72 2
|
4月前
|
人工智能 算法 Java
LeetCode经典算法题:井字游戏+优势洗牌+Dota2参议院java解法
LeetCode经典算法题:井字游戏+优势洗牌+Dota2参议院java解法
54 1
下一篇
DataWorks