图(graph)

图可以分为以下三种:

image.png

无向图: 就行朋友关系一样,你是我们的朋友,那么我也就是你的朋友;
有向图:有向图就像粉丝和偶像的关系,你是我的粉丝,我不一定是你的粉丝;
带权图:就像地铁站各个站点之间的关系,不仅仅是相互连接,站与站之间还有距离的差距。带权图又可以分为无向带权图和有向带权图。

图中的各个概念

图中的元素我们称之为顶点(vertex);顶点之间的连写称之为;对于无向图来说,顶点连接的边的个数称之为;对于有向图来说,指向顶点的边数称为入度;从顶点出来的边数称为出度

图的表示方法

图有两种表示方式:
邻接矩阵法:用矩阵来存储,如下图所示,优点就是定位简单,因为数组支持直接下标索引;缺点就是浪费空间,对于无向图有一半是没用的,对于稀疏图,好多空间闲置。

image.png

邻接表法:邻接表法如下,每个顶点所连接的顶点用链表连接起来。

image.png

图的最短路径查找

广度优先(BFS)搜索算法:顾名思义就是层层推进的搜索方式,先搜索离起点最近的顶点,然后依次往后搜索;因为是从近往远搜索,所以最先找到的肯定是距离最近的

image.png

public void bfs(int start, int end){
        if(start == end) return;
        boolean[] visited = new boolean[v];
        visited[start] = true;
        int[] prev = new int[v];
        for(int i = 0; i < v; i++){
            prev[i] = -1;
        }
        Queue<Integer> queue = new LinkedList<Integer>();
        queue.add(start);
        while(!queue.isEmpty()){
            int current = queue.poll();
            for(int i = 0; i < adj[current].size(); i++){
                int next = adj[current].get(i);
                if(visited[next] == true){
                    continue;
                }
                prev[next] = current;
                visited[next] = true;
                if(next == end){
                    print(prev, start, end);
                    return;
                }
                queue.offer(next);
            }
        }
    }

深度优先算法(DFS) 顾名思义就是一条分支走到底,遍历完之后再向上回溯走下一个分支。
java代码实现如下

public void dfs(int start, int end){
        if(start == end) return;
        boolean[] visited = new boolean[v];
        int[] prev = new int[v];
        for(int i = 0; i < v; i++){
            prev[i] = -1;
        }
        Stack<Integer> stack = new Stack<Integer>();
        visited[start] = true;
        stack.push(start);
        while(!stack.empty()){
            int current = stack.pop();
            for(int i = 0; i < adj[current].size(); i++){
                if(visited[adj[current].get(i)] == true){
                    continue;
                }
                visited[adj[current].get(i)] = true;
                prev[adj[current].get(i)] = current;

                if(adj[current].get(i) == end){
                    print(prev, start, end);
                    return;
                }
                stack.push(adj[current].get(i));
            }
        }
    }
    private void print(int[] prev, int start, int end) {
        int last = prev[end];
        if(last != -1 && end != start){
            print(prev, start, last);
        }
        System.out.print(" " + end);
    }
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 线性表是一对一,树是一对多,图是多对多的关系。 图中的数据元素我们称为顶点(相对于树中的结点),顶点集合不能为空,...
    XDgbh阅读 14,429评论 0 0
  • 图看起来就像下图这样: 在计算机科学中,一个图就是一些顶点的集合,这些顶点通过一系列边结对(连接)。顶点用圆圈表示...
    唐先僧阅读 147,355评论 12 96
  • 基本概念 数据元素之间是一种多对多的关系,用罗辑边标识元素之间的关系; 线性表中数据称为 元素,树中将元素称为 结...
    liangxifeng833阅读 4,781评论 0 2
  • 图是一种比线性表和树更复杂的数据结构,在图中,结点之间的关系是任意的,任意两个数据元素之间都可能相关。图是一种多对...
    Alent阅读 6,887评论 1 22
  • 我不过也是常人,有常人经常都会普遍的事情和情况。 这就是生活,我也没有办法我有情绪和失控。有愤怒有不满有冲突,有憎恶。
    吉祥微创阅读 1,300评论 0 0