图的存储方法(java)及图的深度优先搜索和广度优先搜索

本文大部分参考:数据结构与算法java 作者:周鹏
pdf版下载地址

邻接矩阵法

图的邻接矩阵( adjacent matrix) 表示法是使用数组来存储图结构的方法,也被称为数组表示法。它采用两个数组来表示图:一个是用于存储所有顶点信息的一维数组,另一个是用于存储图中顶点之间关联关系的二维数组,这个关联关系数组也被称为邻接矩阵。
假设图G=(V , E)有n个顶点,即V={v0,v1,…,vn-1},则表示G中各顶点关联关系的为一个n×n的矩阵A,当两个顶点之间有边连接时,对应的元素表示边的权值,否则表示为无穷。
优点:
1. 表示方法非常直观简单,很容易确定两个顶点之间是否有边。

缺点
1. 空间需求为n^2。一般来说,图的边远远达不到n^2。造成空间的浪费
2. 二维数组静态分配,不够灵活

邻接表

邻接表是图的一种链式存储方法,在邻接表中对于图G中的每个顶点vi建立一个单链表,将所有邻接于vi的顶点vj链成一个单链表。在无向图的邻接表中,顶点vi的度恰为顶点vi的邻接表中结点的个数;而在有向图中,顶点vi的邻接表中边表结点的个数仅为顶点vi的出度,为求顶点vi的入度必须遍历整个邻接表,在所有链表中其邻接点域的值指向vi的位置的结点个数是顶点vi的入度。为了方便求得有向图中顶点的入度,可以建立一个有向图的逆邻接表。将指向vi顶点的边也链接到顶点vi,这样便可方便求得入度。
在邻接表中容易找到一个顶点的邻接点,但是要判定两个顶点vi和vj之间是否有边,则需要搜索顶点vi或顶点vj的邻接表,与邻接矩阵相比不如邻接矩阵方便。

示例

leetcode朋友圈问题
邻接矩阵表示法:

package dataStructureAndAlgorithms;

import java.util.LinkedList;
import java.util.Queue;

public class FriendCircleProblemByAdjacencyMatrix {
    /*
     * M   邻接矩阵
     * visit  是否被访问
     * i   从i出发
     */
    public static void dfs(int[][] M, boolean[] visit,int i){
        for(int j=0;j<M[0].length;j++){
            if(M[i][j] != 0 && !visit[j]){
                visit[j] = true;
                dfs(M,visit,j);
            }
        }
    }

    public static void bfs(int[][] M, boolean[] visit,int i){
        Queue<Integer> toVisitQueue = new LinkedList<Integer>();
        toVisitQueue.add(i);
        while(!toVisitQueue.isEmpty()){
            int temp = toVisitQueue.poll();
            visit[temp] = true; 
            for(int j=0;j<M[0].length;j++  ){
                if(M[temp][j] != 0 && !visit[j]){
                    toVisitQueue.add(j);
                }
            }
        }
    }

    public static int findCircleNum(int[][] M){
        boolean[] visit = new boolean[M[0].length];
        int circle = 0;
        for(int i=0;i<M[0].length;i++){
            if(!visit[i]){
                //bfs(M, visit, i);
                dfs(M, visit, i);
                circle ++;
            }
        }
        return circle;
    }

    public static void main(String[] args) {
        int[][] M1 = {{1,1,0},{1,1,0},{0,0,1}};
        System.out.println(findCircleNum(M1));

        int[][] M2 = {{1,1,0},{1,1,1},{0,1,1}};
        System.out.println(findCircleNum(M2));
    }
}

邻接表表示法:

package dataStructureAndAlgorithms;

import java.util.LinkedList;
import java.util.Queue;

public class FriendCircleProblemByAdjacencyList {

    public static void dfs(Vertex vertex){
        Neighbor neighbor = vertex.getNeighbor();
        while(neighbor != null){
            if(!neighbor.getV().visited){
                neighbor.getV().setVisited(true);
                dfs(neighbor.getV());
            }
            neighbor = neighbor.getNext();
        }
    }

    public static void bfs(Vertex vertex){
        Queue<Vertex> toVisitQueue = new LinkedList<Vertex>();
        toVisitQueue.add(vertex);
        while(!toVisitQueue.isEmpty()){
            Vertex temp = toVisitQueue.poll();
            temp.setVisited(true);
            Neighbor neighbor = temp.getNeighbor();
            while(neighbor != null){
                if(!neighbor.getV().isVisited()){
                    toVisitQueue.add(neighbor.getV());
                }
                neighbor = neighbor.getNext();
            }
        }
    }

    public static int findCircleNum(Vertex[] vertexs, boolean useDfs){
        int circle = 0;
        for(int i=0;i<vertexs.length;i++){
            if(!vertexs[i].isVisited()){
                if(useDfs){
                    dfs(vertexs[i]);
                }else{
                    bfs(vertexs[i]);
                }
                circle ++;
            }
        }
        return circle;
    }

    public static void main(String[] args) {
        //顶点
        Vertex vertex0 = new Vertex();
        vertex0.setNumber(0);
        Vertex vertex1 = new Vertex();
        vertex1.setNumber(1);
        Vertex vertex2 = new Vertex();
        vertex2.setNumber(2);
        Vertex[] vertexs = {vertex0,vertex1,vertex2}; 

        //test1  构造邻接表
        vertex0.setNeighbor(new Neighbor(vertex1));
        vertex1.setNeighbor(new Neighbor(vertex0));
        System.out.println(findCircleNum(vertexs,true));
        vertex0.setVisited(false);
        vertex1.setVisited(false);
        vertex2.setVisited(false);
        System.out.println(findCircleNum(vertexs,false));


        //test2
        vertex0.setNeighbor(null);
        vertex1.setNeighbor(null);
        vertex2.setNeighbor(null);
        vertex0.setNeighbor(new Neighbor(vertex1));
        vertex1.setNeighbor(new Neighbor(vertex0));
        vertex1.setNeighbor(new Neighbor(vertex2));
        vertex2.setNeighbor(new Neighbor(vertex1));
        vertex0.setVisited(false);
        vertex1.setVisited(false);
        vertex2.setVisited(false);
        System.out.println(findCircleNum(vertexs,true));
        vertex0.setVisited(false);
        vertex1.setVisited(false);
        vertex2.setVisited(false);
        System.out.println(findCircleNum(vertexs,false));
    }
    static class Neighbor{
        public Neighbor(Vertex vertex){
            this.v = vertex;
        }
        private Vertex v = null;
        private Neighbor next = null;
        public Vertex getV() {
            return v;
        }
        public void setV(Vertex v) {
            this.v = v;
        }
        public Neighbor getNext() {
            return next;
        }
        public void setNext(Neighbor next) {
            this.next = next;
        }
    }

    static class Vertex{
        private int number;
        private Neighbor neighbor;
        private Vertex nextVertex;
        private boolean visited = false; 


        public boolean isVisited() {
            return visited;
        }
        public void setVisited(boolean visited) {
            this.visited = visited;
        }
        public Vertex getNextVertex() {
            return nextVertex;
        }
        public void setNextVertex(Vertex nextVertex) {
            this.nextVertex = nextVertex;
        }
        public int getNumber() {
            return number;
        }
        public void setNumber(int number) {
            this.number = number;
        }
        public Neighbor getNeighbor() {
            return neighbor;
        }
        public void setNeighbor(Neighbor neighbor) {
            if(neighbor == null){
                this.neighbor = null;
                return;
            }
            neighbor.next = this.neighbor;
            this.neighbor = neighbor;
        }
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值