1. 定义
    (Graph)是由顶点的有穷非空集合顶点之间边的集合组成,通常表示为:G(V, E),G表示一个图,V是图G中顶点的集合,E是图G中边的集合。
    注意:
    a.线性表中把数据元素元素中叫结点中称之为顶点(Vertex)
    b.线性表没有数据元素叫空表中没有结点叫空树,而不允许没有顶点,所以定义中才是顶点的有穷非空集合
    c.线性表中相邻数据元素之间具有线性关系中相邻两层结点具有层次关系中任意两个顶点之间都可能有关系(顶点之间的逻辑关系用边来表示,边集可以为空)。
  2. 图的分类
    a.按有无方向
      无向图(Undirected graphs):顶点+边(无向边Edge(vi, vj));
      

        无向完全图:任意两个顶点都存在边,cntEdge = cntVex * (cntVex - 1) / 2。
          

      有向图(Directed graphs):顶点+弧(有向边Arc<vi, vj>),弧有弧尾(vi)与弧头(vj)之分。
        

        有向完全图:任意两个顶点都存在方向互为相反的两条弧,cntEdge = cntVex * (cntVex - 1)。
          
     
    b.按边(弧)的多少
      简单图*:不存在顶点到其自身的边,且同一条边不重复出现,下图为非简单图;
        
      稀疏图/稠密图:就是相对于边(弧)的多少来说的。
    c。其他分类
      网:边(弧)带权值的图;
        

  3. 图的顶点与边的关系
      a.无向图G=(V, {E}),如果边(v, v')∈E,则称顶点v与v'互为邻接点(Adjacent),即v和v'相邻接。边(v, v')依附于顶点v与v'(或者边(v, v')与顶点v与v'相关联);(注:个人觉得这就是废话,我这条边属于整个图所有边的集合,必然v和v'相邻啊,后面的必然也是废话。)
        a.1.顶点v的度(Degree)是和v相关联的边的数目,记为TD(v)
      b.有向图G=(V, {E}),如果弧<v, v'>∈E,则称顶点v邻接到顶点v',顶点v'邻接自顶点v。弧<v, v'>与顶点v和顶点v'相关联
        b.1.以顶点v为头的弧的数目称为v的入度(InDegree),记为ID(v);以顶点v为尾的弧的数目称为v的出度(OutDegree),记为OD(v)
      c.路径(Path):就简单的理解为一个顶点到另一个顶点走过的边(弧)的集合。
        c.1.简单路径:序列中顶点不重复出现的路径;
        c.2.环(回路):最后一个顶点和第一个顶点相同的路径;
          c.2.1简单环(回路):就是除了最后一个顶点和第一个顶点重复以外,不存在其他顶点重复(左图简单环,右图非简单环)。
            

  4. 连通图相关
    a.无向图中,顶点v到顶点v'存在路径,那么顶点v与顶点v'是连通的;
    b.图中如果对于任意的顶点v与v‘都是连通的,且路径中的每条边都属于E(个人理解,那么该图是连通图。下图1为非连通图,图2为连通图。
      

    c.连通分量:无向图中的极大连通子图;
      注:1.要是子图;
        2.子图要是连通的;
        3.连通子图含有极大顶点数;
        4.具有极大顶点数的连通子图包含依附于这些顶点的所有边。
      上四图说明:图1是一个无向非连通图,但它有两个连通分量,图2和图3。而图4虽然是图1的子图,但它不满足连通子图的极大顶点数。
    d.有向图类似与无向图,只是换了个名字。有向图的连通图叫强连通图,连通分量叫强连通分量
    e.生成树
      e.1.无向图中连通且n个顶点n-1条边叫生成树
      e.2.有向图中一顶点入度为0其余顶点入度为1的是有向树
      e.3.一个有向图若干棵有向树构成森林
  5. 图的存储结构
      a.邻接矩阵
        图的邻接矩阵(Adjacency Matrix)是用两个数组来表示图。顶点(一维数组),边或弧(二维数组(称邻接矩阵))。
          对于无向图,邻接矩阵是个对称矩阵,某顶点的度=邻接矩阵中vi的第i行(或者列)所有元素之和。
          对于有向图,邻接矩阵不是对称矩阵,顶点入度=邻接矩阵中vi的第i列之和,出度=第i行之和。
        图的边上有了权值,也就是网图,邻接矩阵的定义如下:

          注:因为权值只是一般来说才是正值,有时候也可能是0或者负值,所以使用无穷来表示一个不可能的值。
          一个简单的有向网图及其存储结构如下图所示:

        邻接绝阵存储结构代码实现
    // 邻接矩阵方式存储图结构
    typedef char VertexType; // 顶点的类型
    typedef int EdgeType; // 边上的权值类型
    
    #define MAXVEX 100 // 最大顶点数
    #define INFINITY 65535 // 65535 代表 无穷
    
    typedef struct
    {
        VertexType vexs[MAXVEX]; // 顶点表
        EdgeType arc[MAXVEX][MAXVEX]; // 邻接矩阵,看作边表
        int numVertexes, numEdges; // 图中当前的顶点数,边数
    }MGraph;
        创建无向网图代码实现
    // 创建无向网图的邻接矩阵表示,n个顶点,e条边,时间复杂度O(n+n^2+e)
    void CreateMGraph(MGraph *G)
    {
        int i, j, k, w;
        //printf("请输入顶点数和边数:\n");
        printf("input the number of vertex and edge(v, e):\n");
        scanf("%d,%d", &G->numVertexes, &G->numEdges);
        getchar();
        for (i=0; i<G->numVertexes; i++) {
            scanf("%c", &G->vexs[i]);
    //        printf("%c", G->vexs[i]);
        }
    
        for (i=0; i<G->numVertexes; i++) {
            for (j=0; j<G->numVertexes; j++) {
                G->arc[i][j] = INFINITY;
            }
        }
    
        for (k=0; k<G->numEdges; k++) {
           // printf("请输入边(vi, vj)上的下标i, 下标j和权值w:");
            printf("input edge(vi, vj), index of i, j and the weight(w):");
            scanf("%d,%d,%d", &i, &j, &w);
    
            G->arc[i][j] = w;
            G->arc[j][i] = G->arc[i][j]; // 图为无向图,矩阵对称
        }
    }
      b.邻接表
        邻接矩阵的问题:对于边数 相对 顶点数较少的图,该结构对存储空间的浪费较大。
        邻接表(Adjacency List),数组与链表相结合的存储方法。一维数组(顶点,指向第一个邻接点的指针)),单链表(vi的所有邻接点)(无向图称为vi的边表有向图称为vi作为弧尾出边表)。
        一个简单的无向图的邻接表结构如下图:
        一个简单的有向图的邻接表与逆邻接表(方便顶点的入度+以顶点为弧头的弧)结构如下图:

        对于带权值的网图,只需要在邻接表中间添加一个weight的数据域用来存放权值即可。如下图所示:

        邻接表存储结构代码实现
    // 邻接表方式存储图结构
    typedef char VertexType;
    typedef int EdgeType;
    
    #define MAXVEX 100 // 最大顶点数
    
    // 边表结点
    typedef struct _EdgeNode
    {
        int adjvex; // 存储该顶点对应的下标
        EdgeType weight;
        struct EdgeNode *next;
    }EdgeNode;
    
    // 顶点表结点
    typedef struct _VertexNode 
    {
        VertexType data; 
        EdgeNode *firstedge; // 边表头指针
    }VertexNode, AdjList[MAXVEX];
    
    // 邻接表图结构
    typedef struct 
    {
        AdjList adjList;
        int numVertexes, numEdges; // 当前顶点数和边数
    }GraphAdjList;

        创建无向图代码
    // 无向图创建邻接表,时间复杂度O(n+e)
    void createALGraph(GraphAdjList *G)
    {
        int i, j, k;
        EdgeNode *e;
        printf("Input the number of vertextes and edges:\n");
        scanf("%d,%d", &G->numVertexes, &G->numEdges);
        
        getchar();
        for (i=0; i<G->numVertexes; i++) {
            scanf("%c", &G->adjList[i].data);
            G->adjList[i].firstedge = NULL;
        }
        
        for (k=0; k<G->numEdges; k++) { // 建立边表
            printf("Input edge (vi, vj), i and j:\n");
            scanf("%d,%d", &i, &j);
            
            // 其实就是链表的头插法创建链表
            e = (EdgeNode *)malloc(sizeof(EdgeNode));
            e->adjvex = j;
            e->next = G->adjList[i].firstedge;
            G->adjList[i].firstedge = e;
            
            e = (EdgeNode *)malloc(sizeof(EdgeNode));
            e->adjvex = i;
            e->next = G->adjList[j].firstedge;
            G->adjList[i].firstedge = e;
        }
    }

      c.十字链表、邻接多重表、边集数组等结构先不研究了
  6. 图的遍历
      a.深度优先遍历
      
      b.广度优先遍历

转载于:https://www.cnblogs.com/ifpelset/articles/4720057.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值