zoukankan      html  css  js  c++  java
  • 数据结构-图的基本知识和表示

      图是一种基本的非线性数据结构,其相关基本概念介绍太多了,这里就不再重复说了。为了让自己能够复习的印象深刻一些,今天专门总结一些图的基本知识。

    一、基本的知识点

      图包含两个核心要素:顶点和边,一个图可以没有边,但不能没有顶点。

      图分可以分为无向图和有向图,有向图就是在这个图中每一条边都有一个方向,表示从一条边出发到另一条边结束。而无向图的边则没有方向。

      图的顶点存在“度”这个概念,对于无向图而言,顶点的度即是这个顶点连接的边的条数就是当前顶点的"度";对于有向图而言,顶点的度又分为出度和入度,出度就是从当前顶点出发的边的条数,入度就是以当前顶点为结尾的边的条数。

      平行边:两个顶点之间可通过两条或者多条边相连,这些边称之为平行边。

      环:一条将顶点连接到它自身的边。

      简单图:无环、无平行边。

      连通图:图中任意两个顶点之间皆存在路径。

      对于一个图G,它的子图的顶点集合是G中顶点的子集,子图的边的集合也是G中边的子集。

      对于无向连通图:

        回路:始于一个顶点,终于同一个顶点的封闭路径。

        无回路的连通图是一棵树。

        连通图的生成树:它是图的一个子图,包含了原图的所有顶点,但是包含了保持连通的最少边数。

    二、图的表示

      表示图就是在程序中存储它的顶点和边,一般使用数组或者线性表存储图的数据结构。

      1、表示顶点

      顶点可以存储在数组或者线性表中,其中顶点可以是任意类型的对象,也可以是基本数据类型。

      2、表示边

      边的表示方法有很多,可以是边数组、边对象、邻接矩阵、邻接线性表等。

      (1)边数组

        就是一个二维数组,第一维的大小是图中边的总数,第二位的大小是2,即边的两个顶点。数组是int型的,存储的边的两个顶点就是顶点数组中对应这两个顶点的索引。

      (2)边对象

        定义一个边对象,包含两个成员变量u、v,表示边的两个顶点,然后重写equals方法,用于判断两个边对象是否相同。

    public class Edge {
        int u;
        int v;
    
        @Override
        public boolean equals(Object obj) {
            return (u == ((Edge)obj).u) && (v == ((Edge)obj).v);
        }
    
        public int getU() {
            return u;
        }
    
        public void setU(int u) {
            this.u = u;
        }
    
        public int getV() {
            return v;
        }
    
        public void setV(int v) {
            this.v = v;
        }
    }

      (3)邻接矩阵

        邻接矩阵也是一个二维数组,但是不同于边数组的是,它的大小是n*n,n是顶点个数,即如果顶点i到顶点j之间有边,那么array[i][j]=1,否则等于0。对于无向图而言邻接矩阵是对称的,所以为了节省空间,可以采用锯齿矩阵进行存储。对于有向图,因为边是有方向的,所以不存在对称这一概念。

      (4)邻接线性表

        邻接线性表分为邻接顶点线性表和邻接边线性表。邻接顶点线性表包含了与一个顶点相连的所有顶点。邻接边线性表包含了与一个顶点相连的所有的边。邻接线性表具体的数据结构是,有一个大小为n的线性表数组,这个线性表数组的每一个元素也是一个线性表。

        邻接顶点线性表可以定义为:

    ArrayList<ArrayList<Integer>> neighbor = new ArrayList<>();

        邻接边线性表可以定义为:

     ArrayList<ArrayList<Edge>> neighbor = new ArrayList<>();

           构建一个邻接边线性表:

    neighbor.add(new ArrayList<Edge>());
    neighbor.get(0).add(new Edge(0,1));
    neighbor.get(0).add(new Edge(0,3));
    neighbor.get(0).add(new Edge(0,5));
            
    neighbor.add(new ArrayList<Edge>());
    neighbor.get(1).add(new Edge(1,0));
    
        ……

      邻接矩阵和邻接线性表都可以表示一个图,但是二者在不同的应用场景下有不同的优点。如果图比较稠密,即含有的边比较多,那么采用邻接矩阵会更好一些,这样的查询效率高,只需常数时间复杂度就可以查询两个点之间是否存在边,并且存储带权重的边也非常方便,但是如果图很稀疏,那么使用邻接矩阵就会很不划算,浪费很多空间,这时使用邻接线性表会更好,能够有效地节省空间。

      

  • 相关阅读:
    Hash
    字符串hash
    NOIp 2014解方程
    NOIp2014 寻找道路
    NOIp2013火柴排队
    用scanf("%d",)读入long long类型
    lis问题
    西江月·证明
    计算系数
    积木大赛&PLA-Postering
  • 原文地址:https://www.cnblogs.com/yxym2016/p/13090382.html
Copyright © 2011-2022 走看看