本文介绍了一种图的数据结构实现方法,并详细阐述了图的深度优先遍历和广度优先遍历的过程。此外,还深入探讨了普利姆算法用于求解最小生成树的具体步骤。

图的一些知识的整理

import java.util.LinkedList;

/**
 * 图的创建-->邻接矩阵
 *
 * */
public class Graph {
    private int vertexSize; //顶点数量

    private  int[] vertexs; // 结点数组(存储每一个结点的编号)

    private int[][] matrix; // 邻接矩阵

    private final int MAX_WEIGHT = 1000; // 不能到达的路的权值

    private boolean[] isVisited;

    public Graph(int vertexSize){
        this.vertexSize = vertexSize;
        this.matrix = new int[vertexSize][vertexSize];
        this.vertexs = new int[vertexSize];
        for (int i = 0;i<vertexSize;i++){
            vertexs[i] = i;            // 表示V0--V4
        }
        isVisited = new boolean[vertexSize];
    }

    /**
     *
     * 获得某结点的出度
     * */

    public int getOutDegree(int index){
        int degree = 0;
        for (int j=0;j<this.matrix[index].length;j++){
            int wight = this.matrix[index][j];
            if (wight>0 && wight < this.MAX_WEIGHT){
                degree++;
            }
        }
       return  degree;

    }

    /**
     *
     * 获取两个顶点之间的权值
     *
     * */

    public int getWeigth(int v1,int v2){
        int weight = this.matrix[v1][v2];
        return ( weight==0 )? (0) :(weight<this.MAX_WEIGHT ? weight : -1);
    }

    /**
     * 获取第一个邻接点
     * */
    public int getFirstNeifhbor(int index){
        for (int j=0;j<this.matrix[index].length;j++){
            if (matrix[index][j]> 0 && matrix[index][j]<MAX_WEIGHT){
                return j;
            }
        }
        return -1;
    }

    /**
     * 获取此结点相对于(某结点)的下一个邻接点
     * @param  v1 代表要查邻接点的的结点
     *
     * @param v2 代表相对于v1的邻接点
     * */

    public int getNextNeighbor(int v1,int v2){
        for (int j = v2+1;j<matrix[v1].length;j++){
            if (matrix[v1][j]> 0 && matrix[v1][j]<MAX_WEIGHT){
                return j;
            }
        }
        return -1;
    }





    /**
     * 图的深度优先遍历
     * */
    private void depthFirstSearch(int index){
        // 标记此节点被访问
        isVisited[index] = true;
        // 得到它的第一个邻接点
        int w = this.getFirstNeifhbor(index);
        //如果有邻接点进入循环
        while(w!=-1){
            //查看这个邻接点是否被访问过了
            if(!isVisited[w]){

                System.out.println("访问到了"+w+"结点");
                // 遍历邻接结点的邻接结点
                depthFirstSearch(w);
            }

            w = this.getNextNeighbor(index,w); // 第一个相对于w的邻接结点

        }

    }

    /**
     * 防止有些顶点达不到
     *这样做的目的是强制遍历所有结点
     *
     * */
    public void depthFirstSearch(){
        isVisited = new boolean[vertexSize];

        for (int i=0;i<vertexSize;i++){
            if(!isVisited[i]){
                System.out.println("访问第"+i+"结点");
                depthFirstSearch(i);
            }

        }

        //遍历完成之后将标记全部初始化
        isVisited = new boolean[vertexSize];

    }


    /**
     *
     * 图的广度优先遍历
     * */
    private void broadFirstSearch(int index){

        int u,w;
        LinkedList<Integer> queue = new LinkedList<>();
        System.out.println("访问到第"+index+"个结点");
        isVisited[index] = true;
        queue.add(index);
        while(!queue.isEmpty()){
             u = queue.removeFirst();
             w = getFirstNeifhbor(u);

            while (w!=-1){
                if(!isVisited[w]){

                    System.out.println("访问到第"+ w +"结点");
                    queue.add(w);
                    isVisited[w] = true;
                }

                w = getNextNeighbor(u,w);
            }

        }

    }


    public void broadFirstSearch(){
        isVisited = new boolean[vertexSize];
        LinkedList<Integer> queue = new LinkedList<>();

        for (int i=0;i<vertexSize;i++){
            if (!isVisited[i]){
                broadFirstSearch(i);
            }

        }

    }

   

    /**
     * 普利姆算法
     * */
    public void prim(){

        /**
        *   存放当前所能到达的最小权值,因为要遍历完整个二维数组,所以可能某些值是虚拟的
            最小权值,之后可能会更新,因为当前只能到达这些顶点了嘛
        * lowcoat 的解释
        * */

        int[] lowcost = new int[vertexSize];

        int[] adjvex = new int[vertexSize];  // 存放最小权值的顶点,最小权值顶点为:最小生成树的顶点
        // min 表示最短的路径长度
        int min,minId,sum = 0;

        // 先随机选择一个顶点作为初始顶点
        //默认我们选V0为第一个最小权值顶点
        // 因为你最终要选完所有的顶点,所以你选的顶点不影响全局
        // 然后让那个lowcost为你所选顶点能到达的所有边的权值
        // 此处要注意: i 是从1开始赋值的,因为你已经把零选过了
        for (int i = 1;i<vertexSize;i++){
            lowcost[i] = matrix[0][i];
        }

        for (int i = 1;i<vertexSize;i++){

            min = MAX_WEIGHT;
            minId = 0;

            for (int j = 1;j<vertexSize;j++){
                // 选出lowcost中最小的值,就为要选的路了
                if(lowcost[j] < min && lowcost[j]>0){
                    min = lowcost[j];
                    minId = j; // 记录当先最小顶点的ID
                }
            }
            System.out.println("顶点"+adjvex[minId]+"权值"+min);
            sum += min;
            lowcost[minId] = 0; // lowcost=0 表明你已经选了这个顶点作为当先最小的权值顶点
            for (int j =1; j<vertexSize;j++){
                //从你选的这个顶点开始寻找可到达的路
                if (lowcost[j]!=0 && matrix[minId][j] < lowcost[j]){
                    // 如果这些路的权值有比我们lowcost中小的,则更新啊lowcost的值
                    // 注意就当你更新了,也不代表这个值就是最小的路径,所以还要进行下一次的循环,遍历(上面的代码)
                    // 选出最小的出来
                    lowcost[j] = matrix[minId][j]; // 更新
                    adjvex[j] = minId;    //记录最小权值顶点
                }
            }

        }
        System.out.println(sum);
    }

    public int[] getVertexs() {
        return vertexs;
    }

    public void setVertexs(int[] vertexs) {
        this.vertexs = vertexs;

    }


    public static void main(String[] args){
       // Graph graph = new Graph(5);
       /* int[] a0 = {0,graph.MAX_WEIGHT,graph.MAX_WEIGHT,graph.MAX_WEIGHT,6};
        int[] a1 = {9,0,3,graph.MAX_WEIGHT,graph.MAX_WEIGHT};
        int[] a2 = {2,graph.MAX_WEIGHT,0,5,graph.MAX_WEIGHT};
        int[] a3 = {graph.MAX_WEIGHT,graph.MAX_WEIGHT,graph.MAX_WEIGHT,0,1};
        int[] a4 = {graph.MAX_WEIGHT,graph.MAX_WEIGHT,graph.MAX_WEIGHT,graph.MAX_WEIGHT,0};
        */
        Graph graph = new Graph(9);
        int[] a0 = {0,10,graph.MAX_WEIGHT,graph.MAX_WEIGHT,graph.MAX_WEIGHT,11,graph.MAX_WEIGHT,graph.MAX_WEIGHT,graph.MAX_WEIGHT};
        int[] a1 = {10,0,18,graph.MAX_WEIGHT,graph.MAX_WEIGHT,graph.MAX_WEIGHT,16,graph.MAX_WEIGHT,12};
        int[] a2 = {graph.MAX_WEIGHT,graph.MAX_WEIGHT,0,22,graph.MAX_WEIGHT,graph.MAX_WEIGHT,graph.MAX_WEIGHT,graph.MAX_WEIGHT,8};
        int[] a3 = {graph.MAX_WEIGHT,graph.MAX_WEIGHT,22,0,20,graph.MAX_WEIGHT,graph.MAX_WEIGHT,16,21};
        int[] a4 = {graph.MAX_WEIGHT,graph.MAX_WEIGHT,graph.MAX_WEIGHT,20,0,26,graph.MAX_WEIGHT,7,graph.MAX_WEIGHT};
        int[] a5 = {11,graph.MAX_WEIGHT,graph.MAX_WEIGHT,graph.MAX_WEIGHT,26,0,17,graph.MAX_WEIGHT,graph.MAX_WEIGHT};
        int[] a6 = {graph.MAX_WEIGHT,16,graph.MAX_WEIGHT,graph.MAX_WEIGHT,graph.MAX_WEIGHT,17,0,19,graph.MAX_WEIGHT};
        int[] a7 = {graph.MAX_WEIGHT,graph.MAX_WEIGHT,graph.MAX_WEIGHT,16,7,graph.MAX_WEIGHT,19,0,graph.MAX_WEIGHT};
        int[] a8 = {graph.MAX_WEIGHT,12,8,21,graph.MAX_WEIGHT,graph.MAX_WEIGHT,graph.MAX_WEIGHT,graph.MAX_WEIGHT,0};


        graph.matrix[0] = a0;
        graph.matrix[1] = a1;
        graph.matrix[2] = a2;
        graph.matrix[3] = a3;
        graph.matrix[4] = a4;
        graph.matrix[5] = a5;
        graph.matrix[6] = a6;
        graph.matrix[7] = a7;
        graph.matrix[8] = a8;

        System.out.println("深度优先遍历");
        graph.depthFirstSearch();
     
        System.out.println("广度优先遍历");
        graph.broadFirstSearch();
       /* int degree = graph.getOutDegree(2);
        System.out.println("出度:"+degree);
        int weigth = graph.getWeigth(0,4);
        System.out.println("权值:"+weigth);
        */
       graph.prim();
    }



}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值