美文网首页算法
Java数据结构算法(四)图

Java数据结构算法(四)图

作者: Active_Loser | 来源:发表于2018-08-03 23:57 被阅读0次

    本文旨作于收集整理使用!!

    导航

    一、图的简介

    图(Graph)是由顶点的有穷非空集合和顶点之间边的集合组成,通常表示为:G(V,E),其中,G表示一个图,V是图G中顶点的集合,E是图G中边的集合。在图中的数据元素,我们称之为顶点(Vertex),顶点集合有穷非空。在图中,任意两个顶点之间都可能有关系,顶点之间的逻辑关系用边来表示,边集可以是空的。
    图主要运用在路径规划以及模型建立中。

    二、图的分类

    1、 无向图

    若顶点v1到v2之间的边没有方向,则称这条边为无向边。如果图中任意两个顶点之间的边都是无向边,则称该图为无向图。
    在无向图中,若任意两个顶点之间都存在边,则称该图为无向完全图

    无向图.png

    2、 有向图

    有向边:若顶点v1到v2的边有方向,则称这条边为有向边或为弧。
    若图中任意两个顶点之间的连线都是有向边,则称该图为有向图。
    在有向图中,若任意两个顶点之间都存互为相反的两条弧,则称该图为有向完全图

    有向图

    3、其他

    权:有些图的边或弧具有与他相关的数字,这种与图相关的边或弧叫做权。
    连通图:在无向图中任意两个顶点之间都是连通的。
    度:无向图顶点的边数叫做度;有向图的边数叫做出度和入度。

    三、图的存储结构

    图的存储结构较为复杂,无法用简单的顺序存储结构存储,因此使用邻接矩阵来存储图。
    邻接矩阵的存储方式是用一维数组存储顶点信息,用二维数组存储图中边或弧的信息。

    1、无向图

    设图有n个顶点,则邻接矩阵就是一个n×n的方阵,定义为:

    若两个顶点之间有连线则值为1,若无连线则为0。如下图所示

    2、有向图

    设图有n个顶点,则邻接矩阵就是一个n×n的方阵,定义为:

    若两个顶点之间从一个顶点到另一个顶点之间有对应的箭头则为1,无则为0。如下图所示,v1到v0有弧线则为1,而v0到v1无弧则为0.

    3、带权的图

    设图有n个顶点,则邻接矩阵就是一个n×n的方阵,定义为:

    我们将对应连线之间的权作为连线的依据,两定点之间无弧线咋舌为无穷大,有弧线则设为对应的权值。

    4、图的简单实现(JAVA)

    /**
     * Author: Active_Loser
     * Date: 2018/8/1 22:24
     * Content:
     */
    public class Graph {
        private static final int MAX_WEIGHT = 1000;
        private int vertexSize;
        private int[] vertexs;
        private int[][] matrix;
        private boolean[] isVisted;
    
        public Graph(int vertexSize) {
            this.vertexSize = vertexSize;
            matrix = new int[vertexSize][vertexSize];
            vertexs = new int[vertexSize];
            for (int i = 0; i < vertexSize; i++) {
                vertexs[i] = i;
            }
            isVisted = new boolean[vertexSize];
        }
    
        /**
         * 获取某个顶点的出度
         *
         * @param index 顶点下标
         * @return 返回该顶点的出度
         */
        public int getOutDeGree(int index) {
            int deGree = 0;
            for (int i = 0; i < matrix[index].length; i++) {
                int weight = matrix[index][i];
                if (weight != 0 && weight != MAX_WEIGHT) {
                    deGree++;
                }
            }
            return deGree;
        }
    
        /**
         * 获取某个顶点的入度
         *
         * @param index 顶点下标
         * @return 返回该顶点的出度
         */
        public int getIntDeGree(int index) {
            int deGree = 0;
            for (int i = 0; i < vertexSize; i++) {
                int weight = matrix[i][index];
                if (weight != 0 && weight != MAX_WEIGHT) {
                    deGree++;
                }
            }
            return deGree;
        }
    
        /**
         * 获取权值
         *
         * @param v1
         * @param v2
         * @return
         */
        public int getWeight(int v1, int v2) {
            return matrix[v1][v2] == 0 ? 0 : (matrix[v1][v2] == MAX_WEIGHT ? -1 : matrix[v1][v2]);
        }
    
        public int[][] getMatrix() {
            return matrix;
        }
    }
    

    图的构造,实现带权的图

    private static final int MAX_WEIGHT = 1000;
    
        public static void main(String[] args) {
            Graph graph = new Graph(4);
            int[] a0 = {0, MAX_WEIGHT, MAX_WEIGHT, 1};
            int[] a1 = {30, 0, MAX_WEIGHT, MAX_WEIGHT};
            int[] a2 = {4, 15, 0, 5};
            int[] a3 = {MAX_WEIGHT, MAX_WEIGHT, MAX_WEIGHT, 0};
            int[][] matrix = graph.getMatrix();
            matrix[0]=a0;
            matrix[1]=a1;
            matrix[2]=a2;
            matrix[3]=a3;
            //graph.方法
        }
    

    四、图的遍历

    1、图的深度优先遍历

    深度优先遍历(Depth_First_Search(DFS))也被称为深度优先搜索,它是从图中的某个v点出发,访问此顶点,然后从v的未被访问的点邻接点出发深度优先遍历,直到图中所有和v点有路径相通的点都被访问到。
    图的深度优先遍历类似于树的前序遍历,如下图,可以将树转化为图。


    深度优先遍历

    深度优先遍历主要代码,完整代码移至最后。

    /**
         * 深度优先遍历,对外界提供访问
         */
        public void dfs(int index) {
            if (index<0||index>vertexSize-1){
                return;
            }
            //重新初始化
            isVisted = new boolean[vertexSize];
            //优先访问开始的点
            System.out.println("访问到了"+index+"顶点");
            depth_first_search(index);
            //通过遍历查看那些点没有被访问(主要针对于有向图)
            for (int i = 0; i < vertexSize; i++) {
                if (!isVisted[i]) {
                    System.out.println("访问到了"+i+"顶点");
                    depth_first_search(i);
                }
            }
            //重新初始化
            isVisted = new boolean[vertexSize];
        }
    
        /**
         * 提供访问的方法
         * @param index
         */
        private void depth_first_search(int index) {
            isVisted[index] = true;
            int w = getFirstNeighbor(index);
            while (w!=-1){
                if (!isVisted[w]){
                    depth_first_search(w);
                    System.out.println("访问到了"+w+"顶点");
                }
                w=getNextNeighbor(index,w);
            }
        }
    
        //获取某个顶点的第一个邻接点
        private int getFirstNeighbor(int v1) {
            for (int i = 0; i < vertexSize; i++) {
                if (matrix[v1][i] > 0 && matrix[v1][i] < MAX_WEIGHT) {
                    return i;
                }
            }
            return -1;
        }
    
        /**
         * 根据前一个邻接点的下标获取一个邻接点
         *
         * @param v1    表示查找的顶点
         * @param index 表示该顶点相对于哪个邻接点获取下一个邻接点
         * @return
         */
        private int getNextNeighbor(int v1, int index) {
            for (int i = index+1; i < vertexSize; i++) {
                if (matrix[index][i] > 0 && matrix[index][i] < MAX_WEIGHT) {
                    return i;
                }
            }
            return -1;
        }
    

    2、图的广度优先遍历

    图的广度优先遍历,类似于树种的层次遍历,如下图将图转化为可以广层次遍历的树。



    广度优先遍历主要代码,完整代码移至最后。

     /**
         * 实现广度优先遍历
         *
         * @param index
         */
        public void bfs(int index) {
            //重新初始化
            isVisted = new boolean[vertexSize];
            //优先访问开始的点
            System.out.println("访问到了"+index+"顶点");
            depth_first_search(index);
            //通过遍历查看那些点没有被访问(主要针对于有向图)
            for (int i = 0; i < vertexSize; i++) {
                if (!isVisted[i]) {
                    System.out.println("访问到了" + i + "顶点");
                    broadFirstSearch(i);
                }
            }
            //重新初始化
            isVisted = new boolean[vertexSize];
    
        }
    
        /**
         * 广度优先遍历算法
         *
         * @param index
         */
        private void broadFirstSearch(int index) {
            int u, w;
            //使用队列实现
            LinkedList<Integer> queue = new LinkedList<>();
            isVisted[index] = true;
            queue.add(index);
            while (!queue.isEmpty()){
                u= queue.removeFirst();
                w=getFirstNeighbor(u);
                while (w!=-1){
                    if (!isVisted[w]){
                        System.out.println("访问到了" + w + "顶点");
                        isVisted[w]=true;
                        queue.add(w);
                    }
                    w=getNextNeighbor(u,w);
                }
            }
        }
     //获取某个顶点的第一个邻接点
        private int getFirstNeighbor(int v1) {
            for (int i = 0; i < vertexSize; i++) {
                if (matrix[v1][i] > 0 && matrix[v1][i] < MAX_WEIGHT) {
                    return i;
                }
            }
            return -1;
        }
    
        /**
         * 根据前一个邻接点的下标获取一个邻接点
         *
         * @param v1    表示查找的顶点
         * @param index 表示该顶点相对于哪个邻接点获取下一个邻接点
         * @return
         */
        private int getNextNeighbor(int v1, int index) {
            for (int i = index + 1; i < vertexSize; i++) {
                if (matrix[index][i] > 0 && matrix[index][i] < MAX_WEIGHT) {
                    return i;
                }
            }
            return -1;
        }
    

    完整代码

    import java.util.LinkedList;
    
    /**
     * Author: Active_Loser
     * Date: 2018/8/1 22:24
     * Content:
     */
    public class Graph {
        private static final int MAX_WEIGHT = 1000;
        private int vertexSize;
        private int[] vertexs;
        private int[][] matrix;
        private boolean[] isVisted;
    
    
        public Graph(int vertexSize) {
            this.vertexSize = vertexSize;
            matrix = new int[vertexSize][vertexSize];
            vertexs = new int[vertexSize];
            for (int i = 0; i < vertexSize; i++) {
                vertexs[i] = i;
            }
            isVisted = new boolean[vertexSize];
        }
    
        /**
         * 深度优先遍历,对外界提供访问
         */
        public void dfs(int index) {
            if (index < 0 || index > vertexSize - 1) {
                return;
            }
            //重新初始化
            isVisted = new boolean[vertexSize];
            //优先访问开始的点
            System.out.println("访问到了" + index + "顶点");
            depth_first_search(index);
            //通过遍历查看那些点没有被访问(主要针对于有向图)
            for (int i = 0; i < vertexSize; i++) {
                if (!isVisted[i]) {
                    System.out.println("访问到了" + i + "顶点");
                    depth_first_search(i);
                }
            }
            //重新初始化
            isVisted = new boolean[vertexSize];
        }
    
        /**
         * 提供访问的方法
         *
         * @param index
         */
        private void depth_first_search(int index) {
            isVisted[index] = true;
            int w = getFirstNeighbor(index);
            while (w != -1) {
                if (!isVisted[w]) {
                    depth_first_search(w);
                    System.out.println("访问到了" + w + "顶点");
                }
                w = getNextNeighbor(index, w);
            }
        }
    
        //获取某个顶点的第一个邻接点
        private int getFirstNeighbor(int v1) {
            for (int i = 0; i < vertexSize; i++) {
                if (matrix[v1][i] > 0 && matrix[v1][i] < MAX_WEIGHT) {
                    return i;
                }
            }
            return -1;
        }
    
        /**
         * 根据前一个邻接点的下标获取一个邻接点
         *
         * @param v1    表示查找的顶点
         * @param index 表示该顶点相对于哪个邻接点获取下一个邻接点
         * @return
         */
        private int getNextNeighbor(int v1, int index) {
            for (int i = index + 1; i < vertexSize; i++) {
                if (matrix[index][i] > 0 && matrix[index][i] < MAX_WEIGHT) {
                    return i;
                }
            }
            return -1;
        }
    
        /**
         * 实现广度优先遍历
         *
         * @param index
         */
        public void bfs(int index) {
            //重新初始化
            isVisted = new boolean[vertexSize];
            //优先访问开始的点
            System.out.println("访问到了"+index+"顶点");
            depth_first_search(index);
            //通过遍历查看那些点没有被访问(主要针对于有向图)
            for (int i = 0; i < vertexSize; i++) {
                if (!isVisted[i]) {
                    System.out.println("访问到了" + i + "顶点");
                    broadFirstSearch(i);
                }
            }
            //重新初始化
            isVisted = new boolean[vertexSize];
    
        }
    
        /**
         * 广度优先遍历算法
         *
         * @param index
         */
        private void broadFirstSearch(int index) {
            int u, w;
            //使用队列实现
            LinkedList<Integer> queue = new LinkedList<>();
            isVisted[index] = true;
            queue.add(index);
            while (!queue.isEmpty()){
                u= queue.removeFirst();
                w=getFirstNeighbor(u);
                while (w!=-1){
                    if (!isVisted[w]){
                        System.out.println("访问到了" + w + "顶点");
                        isVisted[w]=true;
                        queue.add(w);
                    }
                    w=getNextNeighbor(u,w);
                }
            }
        }
    
        /**
         * 获取某个顶点的出度
         *
         * @param index 顶点下标
         * @return 返回该顶点的出度
         */
        public int getOutDeGree(int index) {
            int deGree = 0;
            for (int i = 0; i < matrix[index].length; i++) {
                int weight = matrix[index][i];
                if (weight != 0 && weight != MAX_WEIGHT) {
                    deGree++;
                }
            }
            return deGree;
        }
    
        /**
         * 获取某个顶点的入度
         *
         * @param index 顶点下标
         * @return 返回该顶点的出度
         */
        public int getIntDeGree(int index) {
            int deGree = 0;
            for (int i = 0; i < vertexSize; i++) {
                int weight = matrix[i][index];
                if (weight != 0 && weight != MAX_WEIGHT) {
                    deGree++;
                }
            }
            return deGree;
        }
    
        /**
         * 获取权值
         *
         * @param v1
         * @param v2
         * @return
         */
        public int getWeight(int v1, int v2) {
            return matrix[v1][v2] == 0 ? 0 : (matrix[v1][v2] == MAX_WEIGHT ? -1 : matrix[v1][v2]);
        }
    
        public int[][] getMatrix() {
            return matrix;
        }
    }
    
    

    相关文章

      网友评论

        本文标题:Java数据结构算法(四)图

        本文链接:https://www.haomeiwen.com/subject/tizmmftx.html