图论-邻接矩阵遍历搜索(Java)

图中的元素称为“顶点”,如果两个顶点是连通的,连通的线叫作“边”,两点之间的距离叫作“权”,对于无向边(AB顶点相连,则A可以到达B,B也可以到达A),顶点A的边数叫作“度”;有向边,顶点A的边数叫作出度(AB顶点相连,A可以到达B,但B不能到达A)和入度(AB顶点相连,A不能到达B,B能到达A)。
邻接矩阵的存储结构是用两个数组来表示,一个一维数组存储顶点,一个二维数据(矩阵)存储边的关系



代码表示如下:

    /**
     * 图论-邻接矩阵
     */
    public static class Graph {
        private int[] vertices; // 顶点
        private int[][] matrix; // 图的节点的边
        private int verticeSize; // 顶点的数量

        public Graph(int verticeSize) {
            this.verticeSize = verticeSize;
            vertices = new int[verticeSize];
            matrix = new int[verticeSize][verticeSize];
            
            for(int i = 0; i < verticeSize; i++) {
                vertices[i] = i;
            }
        }
    }

实现一些基本方法:

        /**
         * 获取v1到v2的路径长度
         *
         * @param v1
         * @param v2
         * @return MAX:无穷大,即没有路径 0:本身
         */
        public int getWeight(int v1, int v2) {
            return matrix[v1][v2];
        }

        /**
         * 获取顶点
         *
         * @return
         */
        public int[] getVertices() {
            return vertices;
        }

        /**
         * 获取出度
         *
         * @param v
         * @return
         */
        public int getOutDegree(int v) {
            int count = 0;
            for (int i = 0; i < verticeSize; i++) {
                //matrix[v][v]的一行中存放的数组为v到别的顶点的权
                if (matrix[v][i] != 0 && matrix[v][i] != MAX) {
                    count++;
                }
            }

            return count;
        }

        /**
         * 获取入度
         *
         * @param v
         * @return
         */
        public int getInDegree(int v) {
            int count = 0;
            for (int i = 0; i < verticeSize; i++) {
                //matrix[v][v]的一列中存放的为别的顶点到v的权
                if (matrix[i][v] != 0 && matrix[i][v] != MAX) {
                    count++;
                }
            }

            return count;
        }

图的遍历:
1.深度优先遍历,和二叉树的深度优先遍历差不多

        /**
         * 获取v的第一个邻接点
         *
         * @param v
         */
        private int getFirstNeightbor(int v) {
            return getNeightbor(v, -1);
        }

        /**
         * 获取index以后的v的邻接点,不包含index
         *
         * @param v
         * @param index
         * @return
         */
        private int getNeightbor(int v, int index) {
            for (int i = index + 1; i < verticeSize; i++) {
                if (matrix[v][i] != 0 && matrix[v][i] != MAX) {
                    return i;
                }
            }

            return -1;
        }

        /**
         * 深度优先遍历
         */
        public void dfs() {
            isVisited = new boolean[verticeSize];

            for (int i = 0; i < verticeSize; i++) {
                dfs(i);
            }
        }

        private void dfs(int i) {
            if (!isVisited[i]) {//输出i顶点
                isVisited[i] = true;
                System.out.print(vertices[i]);
            } else {//访问过了,后面也没必要深度遍历了
                return;
            }

            int next = getFirstNeightbor(i);
            while (next != -1) {//以next进行深度遍历
                if (!isVisited[next])
                    dfs(next);
                next = getNeightbor(i, next);
            }
        }

测试代码:

        Graph graph = new Graph(4);
        graph.matrix[0] = new int[]{0, Graph.MAX, 34, Graph.MAX};
        graph.matrix[1] = new int[]{7, 0, Graph.MAX, 45};
        graph.matrix[2] = new int[]{6, Graph.MAX, 0, 34};
        graph.matrix[3] = new int[]{0, 5, 9, 0};
        System.out.println(graph.getInDegree(3));
        System.out.println(graph.getOutDegree(1));

        graph.dfs();

结果:
2
2
0231

2.广度优先遍历

/**
         * 广度优先遍历
         */
        public void bfs() {
            isVisited = new boolean[verticeSize];

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

        private void bfs(int v) {
            if(isVisited[v]) return;

            //输出顶点
            isVisited[v] = true;
            System.out.print(vertices[v]);

            Deque deque = new LinkedList<>();

            //遍历v的所有邻接点
            for (int j = 0; j < verticeSize; j++) {
                if (matrix[v][j] != 0 && matrix[v][j] != MAX) {
                    //入队
                    deque.offer(j);
                }
            }

            while (!deque.isEmpty()) {
                bfs(deque.poll());
            }
        }

测试:

        Graph graph = new Graph(4);
        graph.matrix[0] = new int[]{0, Graph.MAX, 34, Graph.MAX};
        graph.matrix[1] = new int[]{7, 0, Graph.MAX, 45};
        graph.matrix[2] = new int[]{6, Graph.MAX, 0, 34};
        graph.matrix[3] = new int[]{0, 5, 9, 0};
        System.out.println(graph.getInDegree(3));
        System.out.println(graph.getOutDegree(1));

        graph.bfs();

结果:
2
2
0231

类的完整代码:

    /**
     * 图论-邻接矩阵
     */
    public static class Graph {
        private int[] vertices; // 顶点
        private int[][] matrix; // 图的节点的边
        private int verticeSize; // 顶点的数量
        public static final int MAX = Integer.MAX_VALUE;
        private boolean[] isVisited;

        public Graph(int verticeSize) {
            this.verticeSize = verticeSize;
            vertices = new int[verticeSize];
            matrix = new int[verticeSize][verticeSize];

            for (int i = 0; i < verticeSize; i++) {
                vertices[i] = i;
            }
        }

        /**
         * 获取v1到v2的路径长度
         *
         * @param v1
         * @param v2
         * @return MAX:无穷大,即没有路径 0:本身
         */
        public int getWeight(int v1, int v2) {
            return matrix[v1][v2];
        }

        /**
         * 获取顶点
         *
         * @return
         */
        public int[] getVertices() {
            return vertices;
        }

        /**
         * 获取出度
         *
         * @param v
         * @return
         */
        public int getOutDegree(int v) {
            int count = 0;
            for (int i = 0; i < verticeSize; i++) {
                //matrix[v][v]的一行中存放的数组为v到别的顶点的权
                if (matrix[v][i] != 0 && matrix[v][i] != MAX) {
                    count++;
                }
            }

            return count;
        }

        /**
         * 获取入度
         *
         * @param v
         * @return
         */
        public int getInDegree(int v) {
            int count = 0;
            for (int i = 0; i < verticeSize; i++) {
                //matrix[v][v]的一列中存放的为别的顶点到v的权
                if (matrix[i][v] != 0 && matrix[i][v] != MAX) {
                    count++;
                }
            }

            return count;
        }

        /**
         * 获取v的第一个邻接点
         *
         * @param v
         */
        private int getFirstNeightbor(int v) {
            return getNeightbor(v, -1);
        }

        /**
         * 获取index以后的v的邻接点,不包含index
         *
         * @param v
         * @param index
         * @return
         */
        private int getNeightbor(int v, int index) {
            for (int i = index + 1; i < verticeSize; i++) {
                if (matrix[v][i] != 0 && matrix[v][i] != MAX) {
                    return i;
                }
            }

            return -1;
        }

        /**
         * 深度优先遍历
         */
        public void dfs() {
            isVisited = new boolean[verticeSize];

            for (int i = 0; i < verticeSize; i++) {
                dfs(i);
            }
        }

        private void dfs(int i) {
            if (!isVisited[i]) {//输出i顶点
                isVisited[i] = true;
                System.out.print(vertices[i]);
            } else {//访问过了,后面也没必要深度遍历了
                return;
            }

            int next = getFirstNeightbor(i);
            while (next != -1) {//以next进行深度遍历
                if (!isVisited[next])
                    dfs(next);
                next = getNeightbor(i, next);
            }
        }

        /**
         * 广度优先遍历
         */
        public void bfs() {
            isVisited = new boolean[verticeSize];

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

        private void bfs(int v) {
            if(isVisited[v]) return;

            //输出顶点
            isVisited[v] = true;
            System.out.print(vertices[v]);

            Deque deque = new LinkedList<>();

            //遍历v的所有邻接点
            for (int j = 0; j < verticeSize; j++) {
                if (matrix[v][j] != 0 && matrix[v][j] != MAX) {
                    //入队
                    deque.offer(j);
                }
            }

            while (!deque.isEmpty()) {
                bfs(deque.poll());
            }
        }
    }

你可能感兴趣的:(图论-邻接矩阵遍历搜索(Java))