0%

前言

简单对比一下线性表 、图:
在这里插入图片描述
从上图可以看出图结构是很复杂的,研究图结构的一个专门理论工具便是图论。

图的基本概念

图结构:

  • 顶点(Vertex):图中的数据元素。
  • 边(Edge):图中连接这些顶点的线。
    一个完整的图结构由顶点集合和边集合组成。
    G = (V,E)
    其中,V表示图中所有顶点的集合,必须为非空。E表示图中所有边的集合,可以为空,此时表示没有边。

    有向图与无向图

    有向图:在图结构中,边有方向性,这种图便称为有向图。*在表示边时,与顶点的顺序有关。***
    无向图:在图结构中,边没有方向性,这种图便称为无向图。*
    在表示边时,与顶点的顺序无关。***

    子图

    假设有两个图G = (V,E)和G’ = (V’,E’),如果V’∈V E’∈E,则称G’为G的子图。

注意:只有顶点集合是子集,或者只有边集合是子集的,都不是子图。

无向完全图与有向完全图

无向完全图:如果在一个无向图中,每两个顶点之间都存在一条边(即n(n-1)/2条),这种图结构称为无向完全图。
有向完全图:如果在一个有向图中,每两个顶点之间都存在方向相反的两条边(即**n(n-1)**条),这种图结构称为有向完全图。

权和网

在实际应用中,每条边可以标上带有具体含义的数值,该数值称为该边上的
这种带权的图就叫

邻接顶点

两个点确定一条边,这两点就是邻接顶点。
有向图稍微复杂一点,两个顶点分为起始顶点和结束顶点(因为有方向)。

返回目录

顶点的度

连接顶点的边的数量称为顶点的度。
有向图稍微复杂一点,根据方向性可分为入度和出度
入度:箭头指向自己的边的数量。ID(V)。
出度:箭头往外指的边的数量。OD(V)。
D(V)=ID(V)+OD(V)
一般地,所有顶点的度的和加起来除以2等于图的边数:
$$ e=\sum_{i=0}^n D(Vi) $$

路径和路径长度

路径指图结构中两个顶点之间要走的边,路径上边的数量称为路径长度。
在这里插入图片描述
如图所示,从V5 到 V2 其中一条路径为(V5,V4)、(V4,V2),路径长度为2。

回路或环

第一个顶点和最后一个顶点相同的路径称为回路或环。

简单路径与简单回路

简单路径:在图结构中,如果一条路径上的顶点不重复出现,则称为简单路径。
简单回路:在图结构中,如果除了第一个顶点和最后一个顶点相同,其余各顶点都不重复的回路称为简单回路。

连通、连通图和连通分量—-无向图

连通:如果图结构中两个顶点之间有路径,则这两个顶点是连通的。
**注意:连通的两个顶点未必是邻接顶点,只要有路径走得通即可。**

连通图:如果无向图中 任意 两个顶点都是连通的,那么这个图便称为连通图。
该图的连通分量。
对于一个连通图,其连通分量有且只有一个,那就是该连通图自身。

强连通图和强连通分量—-有向图

强连通图:任意两个顶点Vi,Vj,从Vi 到 Vj 和从Vj 到 Vi 都存在路径,那么这个图便称为强连通图。
强连通分量:有向图的极大强连通子图称为该图的强连通分量。
对于一个强连通图,其强连通分量有且只有一个,那就是该强连通图自身。

返回目录

  • 图的存储结构

    • 邻接矩阵

      采用二维数组的形式保存顶点之间的关系。该数组称为邻接矩阵。
      除了一个用于存储邻接矩阵的二维数组外,还需要用一个一维数组来存储顶点信息。
      无权值:
      ![A[i][j]=](https://img-blog.csdnimg.cn/20190710091911355.png

    有权值:
    在这里插入图片描述
    对于无向图,其邻接矩阵左下角和右上角是对称的。

    • 邻接表

      对图中每个顶点Vi建立一个单链表,把与Vi的邻接点放在这个链中。Vi存在头结点中,其余结点存放邻接点边的信息。
      这样邻接表便由两部分组成:**表头结点表和边表。**
      表头结点表:由所有头结点顺序存储,以便可以随机访问任意顶点的边表。结点包括两个域,数据域,存放顶点名。指针域,指向第一个结点(第一个邻接点)。
      边表:结点包括三个域。邻接点域,存放该邻接点在图中的位置。数据域,存放权值。指针域,指向下一邻接点。
                         ![在这里插入图片描述](https://img-blog.csdnimg.cn/20190710155806527.jpg?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3Nvbmdzb25nTA==,size_16,color_FFFFFF,t_70 =300x300)
      ![在这里插入图片描述](https://img-blog.csdnimg.cn/20190710155821686.jpg?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3Nvbmdzb25nTA==,size_16,color_FFFFFF,t_70 =600x300)
    • 邻接矩阵与邻接表的比较

      在这里插入图片描述 返回目录

    图的操作

  • 采用邻接矩阵表示法

    由上面图的基本概念可知,创建图与网的区别就是增加一个权值。
    创建有向无向的区别就是无向可以默认生成 对称信息,有向 来与回 不同步。

    • 初始化

      1
      2
      3
      4
      5
      6
      typedef struct MNode{
      vertexType vertex[MVNum]; //存储顶点
      arcType Arc[MVNum][MVNum]; //邻接矩阵,存储边
      int vexnum,arcnum;
      GraphKind kind; //图的种类,有向无向等
      }GraphNode,*Graph;
    • 创建无向图

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      27
      28
      29
      30
      31
      32
      33
      34
      35
      36
      37
      38
      void CreateUDG(Graph G)			//创建无向图 
      {
      int num=0, //控制输入顶点数
      pos1,pos2, //确认顶点位置
      i,j;
      char a,
      b,
      ch; //顶点
      for(i = 0;i<MVNum;i++){ //初始化弧
      for(j = 0;j<MVNum;j++){
      G->Arc[i][j] = 0;
      }
      }
      G->kind = UDG; //图的类型为无向图

      printf("请输入顶点(不超过10个,以#结束):\n");
      cin>>ch;
      while(ch!='#' && num <10){
      G->vertex[num] = ch;
      cin>>ch;
      num++;
      }
      G->vexnum = num; //顶点个数

      cout<<"请输入对应的弧(ab与ba是一样的边),以##结束"<<endl;
      cin>>a>>b;
      while(a!='#' && b!='#'){
      cout<<a<<"-"<<b<<endl;
      FindPos(G,a,b,pos1,pos2);
      printf("位置a:%d,位置b:%d\n",pos1,pos2);
      if(pos1!= -1 && pos2!= -1){ //忽略不存在的顶点
      G->Arc[pos1][pos2] = 1;
      G->Arc[pos2][pos1] = 1;
      G->arcnum++;
      }
      cin>>a>>b;
      }
      }
    • 创建无向网

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      27
      28
      29
      30
      31
      32
      33
      34
      35
      36
      37
      38
      39
      40
      void CreateUDN(Graph G)			//创建无向网
      {
      int num=0, //控制输入顶点数
      pos1,pos2, //确认顶点位置
      i,j,
      weight; //权值
      char a,
      b,
      ch; //顶点

      for(i = 0;i<MVNum; i++){ //初始化弧
      for(j = 0;j<MVNum; j++){
      G->Arc[i][j] = MAXINT;
      }
      }
      G->kind = UDN; //设置图的类型

      printf("请输入顶点(不超过10个,以#结束):\n");
      cin>>ch;
      while(ch!='#' && num <10){
      G->vertex[num] = ch;
      scanf("%c",&ch);
      num++;
      }
      G->vexnum = num; //顶点个数

      cout<<"请输入对应的弧(ab与ba是一样的边)和权值,以###结束"<<endl;
      cin>>a>>b>>weight;
      while(a!='#' && b!='#'){
      cout<<a<<"-"<<b<<":"<<weight<<endl;
      FindPos(G,a,b,pos1,pos2);
      printf("位置a:%d,位置b:%d\n",pos1,pos2);
      if(pos1!= -1 && pos2!= -1){ //忽略不存在的顶点
      G->Arc[pos1][pos2] = weight;
      G->Arc[pos2][pos1] = weight;
      G->arcnum++;
      }
      cin>>a>>b>>weight;
      }
      }
    • 创建有向图

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      27
      28
      29
      30
      31
      32
      33
      34
      35
      36
      void CreateDG(Graph G)			//创建有向图 
      {
      int num=0, //控制输入顶点数
      pos1,pos2, //确认顶点位置
      i,j;
      char a,
      b,
      ch; //顶点
      for(int i=0;i<MVNum;i++){ //初始化
      for(int j=0;j<MVNum;j++){
      G->Arc[i][j]=0;
      }
      }
      G->kind=DG; //类型为有向图
      cout<<"请输入顶点,以#结束"<<endl;
      cin>>ch;
      while(ch!='#'&&num<10){
      G->vertex[num]=ch;
      cin>>ch;
      num++;
      }
      G->vexnum=num;

      cout<<"请输入对应的弧(ab与ba是方向相反的边),以##结束"<<endl;
      cin>>a>>b;
      while(a!='#'&&b!='#'){
      cout<<a<<"->"<<b<<endl;
      FindPos(G,a,b,pos1,pos2);
      cout<<"位置a:"<<pos1<<"位置b:"<<pos2<<endl;
      if(pos1!=-1&&pos2!=-1){
      G->Arc[pos1][pos2]=1;
      G->arcnum++;
      }
      cin>>a>>b;
      }
      }
    • 创建有向网

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      27
      28
      29
      30
      31
      32
      33
      34
      35
      36
      37
      38
      void CreateDN(Graph G)			//创建有向网 
      {
      int num=0, //控制输入顶点数
      pos1,pos2, //确认顶点位置
      i,j,
      weight; //权值
      char a,
      b,
      ch; //顶点
      for(i = 0;i < MVNum; i++){ //初始化弧
      for(j = 0;j<MVNum; j++){
      G->Arc[i][j] = MAXINT;
      }
      }
      G->kind = DN; //图的类型为有向网

      printf("请输入顶点(不超过10个,以#结束):\n");
      cin>>ch;
      while(ch!='#' && num <10){
      G->vertex[num] = ch;
      cin>>ch;
      num++;
      }
      G->vexnum = num; //顶点个数

      cout<<"请输入对应的弧(ab与ba是方向相反的边)和权值,以###结束"<<endl;
      cin>>a>>b>>weight;
      while(a!='#' && b!='#'){
      cout<<a<<"->"<<b<<":"<<weight<<endl;
      FindPos(G,a,b,pos1,pos2);
      printf("位置a:%d,位置b:%d\n",pos1,pos2);
      if(pos1!= -1 && pos2!= -1){ //忽略不存在的顶点
      G->Arc[pos1][pos2] = weight;
      G->arcnum++;
      }
      cin>>a>>b>>weight;
      }
      }

      返回目录

  • 采用邻接表表示法

    由上面图的基本概念可知,创建图与网的区别就是增加一个权值。
    创建有向无向的区别就是无向可以默认生成 对称信息,有向 来与回 不同步。

    • 创建无向图

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      27
      28
      29
      30
      31
      32
      33
      34
      35
      36
      37
      void CreateUDG(ALGraph &G) {								//采用邻接表表示法,创建无向图G

      int i, k;

      cout << "请输入总顶点数和总边数:" ; //输出总顶点数,总边数
      cin >> G.vexnum >> G.arcnum;
      cout << endl;

      cout << "请输入顶点:" << endl;
      for (i = 0 ; i < G.vexnum; i++) { //输入各点,构建表头结点
      cout << "请输入第" << (i + 1) << "个顶点的名称:";
      cin >> G.vertices[i].data;
      G.vertices[i].fristarrc = NULL; //初始化表头结点的指针域为NULL
      }

      cout << endl;
      cout << "请输入一条边依附的顶点:" <<endl;
      for (k = 0; k < G.arcnum; k++) {
      VerTexType v1, v2;
      int i, j;
      cout << "请输入第" << (k+1) << "条边依附的顶点";
      cin >> v1 >> v2; //输入一条边依附的两个顶点
      i = LocateVex(G, v1); //确定v1和v2在G中的位置,
      j = LocateVex(G, v2); //即顶点在G.vertices(邻接表)中的序号

      ArcNode *p1 = new ArcNode; //生成一个新的边结点*p1
      p1->adjvex = j; //邻接点序号为j
      p1->nextarc = G.vertices[i].fristarrc;
      G.vertices[i].fristarrc = p1; //将新节点*p1插入vi的边表

      ArcNode *p2 = new ArcNode; //生成另一个对称的新的边结点*p2
      p2->adjvex = i; //邻接点序号为i
      p2->nextarc = G.vertices[j].fristarrc;
      G.vertices[j].fristarrc = p2; //将新结点*p2插入顶点Vj的边表

      }
      }
    • 创建无向网

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      27
      28
      29
      30
      31
      32
      33
      34
      35
      36
      37
      38
      39
      void CreateUDN(ALGraph &G) {							//采用邻接表表示法,创建无向网G

      int i, k;

      cout << "请输入总顶点数和总边数:" ; //输出总顶点数,总边数
      cin >> G.vexnum >> G.arcnum;
      cout << endl;

      cout << "请输入顶点:" << endl;
      for (i = 0 ; i < G.vexnum; i++) { //输入各点,构建表头结点
      cout << "请输入第" << (i + 1) << "个顶点的名称:";
      cin >> G.vertices[i].data;
      G.vertices[i].fristarrc = NULL; //初始化表头结点的指针域为NULL
      }

      cout << endl;
      cout << "请输入一条边依附的顶点,和权值" <<endl;
      for (k = 0; k < G.arcnum; k++) {
      VerTexType v1, v2;
      int i, j,weight;
      cout << "请输入第" << (k+1) << "条边依附的顶点";
      cin >> v1 >> v2>>weight; //输入一条边依附的两个顶点
      i = LocateVex(G, v1); //确定v1和v2在G中的位置,
      j = LocateVex(G, v2); //即顶点在G.vertices(邻接表)中的序号

      ArcNode *p1 = new ArcNode; //生成一个新的边结点*p1
      p1->adjvex = j;
      p1->info = weight; //邻接点序号为j
      p1->nextarc = G.vertices[i].fristarrc;
      G.vertices[i].fristarrc = p1; //将新节点*p1插入vi的边表

      ArcNode *p2 = new ArcNode; //生成另一个对称的新的边结点*p2
      p2->adjvex = i;
      p2->info = weight; //邻接点序号为i
      p2->nextarc = G.vertices[j].fristarrc;
      G.vertices[j].fristarrc = p2; //将新结点*p2插入顶点Vj的边表

      }
      }
      返回目录
  • 图的遍历

    因为图中的任意顶点都可能和其余的顶点邻接。所以必须记下每个已访问过的顶点,避免同一顶点被访问多次。设一个辅助数组 IsRead[MVNum]**,初始值为0/false,一旦访问过就置1/true。即 **打卡 操作。

    • 深度优先搜索

    • 广度优先搜索

返回目录

  • 邻接矩阵表示法总的代码:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    184
    185
    186
    187
    188
    189
    190
    191
    192
    193
    194
    195
    196
    197
    198
    199
    200
    201
    202
    203
    204
    205
    206
    207
    208
    209
    210
    211
    212
    213
    214
    215
    216
    217
    218
    219
    220
    221
    222
    223
    224
    225
    226
    227
    228
    229
    230
    231
    232
    233
    234
    235
    236
    237
    238
    239
    240
    241
    242
    243
    244
    245
    246
    247
    248
    249
    250
    251
    252
    253
    254
    255
    256
    257
    258
    259
    260
    261
    262
    263
    264
    265
    266
    267
    268
    269
    270
    271
    272
    273
    274
    275
    276
    277
    278
    279
    280
    281
    282
    283
    284
    285
    286
    287
    288
    289
    290
    291
    292
    293
    294
    295
    296
    297
    298
    299
    300
    301
    302
    303
    304
    305
    306
    307
    308
    309
    310
    311
    312
    313
    314
    315
    316
    317
    318
    319
    320
    321
    322
    323
    324
    325
    326
    327
    328
    329
    330
    331
    332
    333
    334
    335
    336
    337
    338
    339
    340
    341
    342
    343
    344
    345
    346
    347
    348
    349
    350
    351
    352
    353
    354
    355
    356
    357
    358
    359
    360
    361
    362
    363
    364
    365
    366
    367
    368
    369
    370
    371
    372
    373
    374
    375
    376
    377
    378
    379
    380
    381
    382
    383
    #include<iostream>
    #include<stdio.h>
    #include<stdlib.h>
    #include<queue>
    #include<math.h>
    using namespace std;


    #define MVNum 10//最大顶点数
    #define MAXINT 32768//表示极大值
    typedef enum{DG,DN,UDG,UDN} GraphKind; //有向图、有向网、无向图、无向网
    typedef int arcType;
    typedef char vertexType;


    #define MAX_SIZE 20

    /*定义队列*/
    typedef struct QNode{
    int Qarr[MAX_SIZE];
    int tail,head;
    int size;
    }QNode,*Queue;

    void InitQueue(Queue &Q){
    Q= (QNode *)malloc(sizeof(QNode));
    if(Q){
    Q->size = 0;
    Q->head = 0;
    Q->tail = 0;
    }
    }

    int isEmpty(Queue Q){
    if(Q->head == Q->tail)
    return 1;
    return 0;
    }

    int isFull(Queue Q){
    if((Q->tail +1) % MAX_SIZE == Q->head)
    return 1;
    return 0;
    }

    /*入队列*/
    void EnterQueue(Queue Q, int data){
    if(isFull(Q)){
    printf("队列已经满!!\n");
    return;
    }
    Q->Qarr[Q->tail] = data;
    Q->size++;
    Q->tail = (Q->tail +1) % MAX_SIZE;
    return;
    }

    void OutQueue(Queue Q, int &data){
    if(isEmpty(Q)){
    printf("队列为空!!\n");
    return;
    }
    data= Q->Qarr[Q->head];
    Q->size--;
    Q->head = (Q->head +1) % MAX_SIZE;
    return;
    }



    typedef struct MNode{
    vertexType vertex[MVNum]; //存储顶点
    arcType Arc[MVNum][MVNum]; //邻接矩阵,存储边
    int vexnum,arcnum;
    GraphKind kind; //图的种类,有向无向等
    }GraphNode,*Graph;

    int IsRead[MVNum];

    int Init(Graph &G){
    G=(GraphNode *)malloc(sizeof(GraphNode));
    G->vexnum=0;
    G->arcnum=0;
    if(G) return 1;
    else cout<<"初始化出错!"<<endl;
    return 0;
    }

    void FindPos(Graph G,char a,char b,int &pos1,int &pos2){//查找位置
    int i=0;
    pos1=-1;pos2=-1;
    for(int i=0;i<G->vexnum;i++){
    if(G->vertex[i]==a){
    pos1=i;
    continue;
    }
    else if(G->vertex[i]==b){
    pos2=i;
    continue;
    }
    }
    }

    void CreateDG(Graph G) //创建有向图
    {
    int num=0, //控制输入顶点数
    pos1,pos2, //确认顶点位置
    i,j;
    char a,
    b,
    ch; //顶点
    for(int i=0;i<MVNum;i++){ //初始化
    for(int j=0;j<MVNum;j++){
    G->Arc[i][j]=0;
    }
    }
    G->kind=DG; //类型为有向图
    cout<<"请输入顶点,以#结束"<<endl;
    cin>>ch;
    while(ch!='#'&&num<10){
    G->vertex[num]=ch;
    cin>>ch;
    num++;
    }
    G->vexnum=num;

    cout<<"请输入对应的弧(ab与ba是方向相反的边),以##结束"<<endl;
    cin>>a>>b;
    while(a!='#'&&b!='#'){
    cout<<a<<"->"<<b<<endl;
    FindPos(G,a,b,pos1,pos2);
    cout<<"位置a:"<<pos1<<"位置b:"<<pos2<<endl;
    if(pos1!=-1&&pos2!=-1){
    G->Arc[pos1][pos2]=1;
    G->arcnum++;
    }
    cin>>a>>b;
    }
    }

    void CreateDN(Graph G) //创建有向网
    {
    int num=0, //控制输入顶点数
    pos1,pos2, //确认顶点位置
    i,j,
    weight; //权值
    char a,
    b,
    ch; //顶点
    for(i = 0;i < MVNum; i++){ //初始化弧
    for(j = 0;j<MVNum; j++){
    G->Arc[i][j] = MAXINT;
    }
    }
    G->kind = DN; //图的类型为有向网

    printf("请输入顶点(不超过10个,以#结束):\n");
    cin>>ch;
    while(ch!='#' && num <10){
    G->vertex[num] = ch;
    cin>>ch;
    num++;
    }
    G->vexnum = num; //顶点个数

    cout<<"请输入对应的弧(ab与ba是方向相反的边)和权值,以###结束"<<endl;
    cin>>a>>b>>weight;
    while(a!='#' && b!='#'){
    cout<<a<<"->"<<b<<":"<<weight<<endl;
    FindPos(G,a,b,pos1,pos2);
    printf("位置a:%d,位置b:%d\n",pos1,pos2);
    if(pos1!= -1 && pos2!= -1){ //忽略不存在的顶点
    G->Arc[pos1][pos2] = weight;
    G->arcnum++;
    }
    cin>>a>>b>>weight;
    }
    }

    void CreateUDG(Graph G) //创建无向图
    {
    int num=0, //控制输入顶点数
    pos1,pos2, //确认顶点位置
    i,j;
    char a,
    b,
    ch; //顶点
    for(i = 0;i<MVNum;i++){ //初始化弧
    for(j = 0;j<MVNum;j++){
    G->Arc[i][j] = 0;
    }
    }
    G->kind = UDG; //图的类型为无向图

    printf("请输入顶点(不超过10个,以#结束):\n");
    cin>>ch;
    while(ch!='#' && num <10){
    G->vertex[num] = ch;
    cin>>ch;
    num++;
    }
    G->vexnum = num; //顶点个数

    cout<<"请输入对应的弧(ab与ba是一样的边),以##结束"<<endl;
    cin>>a>>b;
    while(a!='#' && b!='#'){
    cout<<a<<"-"<<b<<endl;
    FindPos(G,a,b,pos1,pos2);
    printf("位置a:%d,位置b:%d\n",pos1,pos2);
    if(pos1!= -1 && pos2!= -1){ //忽略不存在的顶点
    G->Arc[pos1][pos2] = 1;
    G->Arc[pos2][pos1] = 1;
    G->arcnum++;
    }
    cin>>a>>b;
    }
    }

    void CreateUDN(Graph G) //创建无向网
    {
    int num=0, //控制输入顶点数
    pos1,pos2, //确认顶点位置
    i,j,
    weight; //权值
    char a,
    b,
    ch; //顶点

    for(i = 0;i<MVNum; i++){ //初始化弧
    for(j = 0;j<MVNum; j++){
    G->Arc[i][j] = MAXINT;
    }
    }
    G->kind = UDN; //设置图的类型

    printf("请输入顶点(不超过10个,以#结束):\n");
    cin>>ch;
    while(ch!='#' && num <10){
    G->vertex[num] = ch;
    scanf("%c",&ch);
    num++;
    }
    G->vexnum = num; //顶点个数

    cout<<"请输入对应的弧(ab与ba是一样的边)和权值,以###结束"<<endl;
    cin>>a>>b>>weight;
    while(a!='#' && b!='#'){
    cout<<a<<"-"<<b<<":"<<weight<<endl;
    FindPos(G,a,b,pos1,pos2);
    printf("位置a:%d,位置b:%d\n",pos1,pos2);
    if(pos1!= -1 && pos2!= -1){ //忽略不存在的顶点
    G->Arc[pos1][pos2] = weight;
    G->Arc[pos2][pos1] = weight;
    G->arcnum++;
    }
    cin>>a>>b>>weight;
    }
    }

    void BuildGraph(Graph G){
    int choose=0; //选择
    cout<<"请选择建立图的类型:"<<endl;
    cout<<"1.有向图 2.有向网"<<endl<<"3.无向图 4.无向网"<<endl;
    cin>>choose;
    cout<<endl;
    switch(choose){
    case 1:CreateDG(G);break;
    case 2:CreateDN(G);break;
    case 3:CreateUDG(G);break;
    case 4:CreateUDN(G);break;
    default:cout<<"ERROR";return;
    }
    }

    void DepthFS(Graph G,int pos){ /*深度优先搜索for图*/
    int i = 0,j = 0;
    if(IsRead[pos] == 0){
    IsRead[pos] = 1; //被访问过,打卡
    printf("遍历顶点%c\n",G->vertex[pos]);
    }

    for(i = 0;i<G->vexnum;i++){
    if(G->Arc[pos][i] == 1 && IsRead[i] ==0){ //存在弧
    DepthFS(G,i);
    }
    }
    }

    void DepthFS1(Graph G,int pos){ /*深度优先搜索for网*/
    int i = 0,j = 0;
    if(IsRead[pos] == 0){
    IsRead[pos] = 1; //被访问过,打卡
    printf("遍历顶点%c\n",G->vertex[pos]);
    }

    for(i = 0;i<G->vexnum;i++){
    if(G->Arc[pos][i] !=INFINITY && IsRead[i] ==0){ //存在弧且未被遍历
    DepthFS1(G,i);
    }
    }
    }

    /*深度优先搜索*/
    void DFS(Graph G){
    if(G->kind == DG || G->kind == UDG){ //图
    DepthFS(G,0);
    }else if(G->kind == DN || G->kind == UDN){ //网
    DepthFS1(G,0);
    }
    }

    void BFS1(Graph G,int pos){ //广度优先搜索for图
    int i = 0,temp;
    Queue Q;
    InitQueue(Q);
    for(i = 0; i<G->vexnum;i++){ //清零
    IsRead[i] = 0;
    }
    if(IsRead[pos] ==0){
    IsRead[pos] = 1;
    printf("遍历顶点:%c\n",G->vertex[pos]);
    }
    EnterQueue(Q,pos);
    while(!isEmpty(Q)){//当队列不为空
    OutQueue(Q,temp);
    for(i = 0; i< G->vexnum;i++){
    if(G->Arc[temp][i] == 1 && IsRead[i] == 0){
    IsRead[i] = 1;
    printf("遍历顶点:%c\n",G->vertex[i]);
    EnterQueue(Q,i);
    }
    }
    }
    free(Q);
    }

    void BFS2(Graph G,int pos){ //广度优先搜索for图
    int i = 0,temp;
    Queue Q;
    InitQueue(Q);
    for(i = 0; i <G->vexnum;i++){ //清零
    IsRead[i] = 0;
    }
    if(IsRead[pos] ==0){
    IsRead[pos] = 1;
    printf("遍历顶点:%c\n",G->vertex[pos]);
    }
    EnterQueue(Q,pos);
    while(!isEmpty(Q)){//当队列不为空
    OutQueue(Q,temp);
    for(i = 0; i< G->vexnum;i++){
    if(G->Arc[temp][i] != INFINITY && IsRead[i] == 0){
    IsRead[i] = 1;
    printf("遍历顶点:%c\n",G->vertex[i]);
    EnterQueue(Q,i);
    }
    }
    }
    free(Q);
    }

    void BFS(Graph G){
    if(G->kind == DG || G->kind == UDG){ //图
    BFS1(G,0);
    }else if(G->kind == DN || G->kind == UDN){ //网
    BFS2(G,0);
    }
    }

    int main(){
    int i = 0;
    Graph G = NULL;
    Init(G);
    BuildGraph(G);
    for(i = 0; i<MVNum; i++){
    IsRead[i] = 0; //未被遍历
    }
    printf("\n深度优先搜索:\n");
    DFS(G);
    printf("\n广度优先搜索:\n");
    BFS(G);
    return 0;
    }

    创建如图所示的图:
    ![在这里插入图片描述](https://img-blog.csdnimg.cn/20190711143608849.jpg?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3Nvbmdzb25nTA==,size_16,color_FFFFFF,t_70 =400x300)

  • 邻接表表示法总的代码:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    184
    185
    186
    187
    188
    189
    190
    191
    192
    193
    194
    195
    196
    197
    198
    199
    #include <iostream>
    #include<queue>
    using namespace std;

    #define MVNum 100 //最大顶点信息
    int IsRead[MVNum];

    typedef char VerTexType;
    typedef int OtherInfo;

    //----------图的邻接表存储表示-----------
    typedef struct ArcNode { //边结点
    int adjvex; //该边所指向顶点的位置
    struct ArcNode *nextarc; //指向下一条边的指针
    OtherInfo info; //和边相关的信息

    }ArcNode;

    typedef struct VNode {
    VerTexType data; //顶点信息
    ArcNode *fristarrc; //指向第一条依附该顶点的边

    } VNode,AdjList[MVNum];

    typedef struct {
    AdjList vertices; // 邻接表
    int vexnum; //图的当前顶点数
    int arcnum; //图的当前边数
    }ALGraph;

    int LocateVex(ALGraph G,VerTexType v) {
    for (int i = 0; i < G.vexnum; i++)
    if (G.vertices[i].data == v)
    return i;
    return -1;
    }

    void CreateUDG(ALGraph &G) { //采用邻接表表示法,创建无向图G

    int i, k;

    cout << "请输入总顶点数和总边数:" ; //输出总顶点数,总边数
    cin >> G.vexnum >> G.arcnum;
    cout << endl;

    cout << "请输入顶点:" << endl;
    for (i = 0 ; i < G.vexnum; i++) { //输入各点,构建表头结点
    cout << "请输入第" << (i + 1) << "个顶点的名称:";
    cin >> G.vertices[i].data;
    G.vertices[i].fristarrc = NULL; //初始化表头结点的指针域为NULL
    }

    cout << endl;
    cout << "请输入一条边依附的顶点:" <<endl;
    for (k = 0; k < G.arcnum; k++) {
    VerTexType v1, v2;
    int i, j;
    cout << "请输入第" << (k+1) << "条边依附的顶点";
    cin >> v1 >> v2; //输入一条边依附的两个顶点
    i = LocateVex(G, v1); //确定v1和v2在G中的位置,
    j = LocateVex(G, v2); //即顶点在G.vertices(邻接表)中的序号

    ArcNode *p1 = new ArcNode; //生成一个新的边结点*p1
    p1->adjvex = j; //邻接点序号为j
    p1->nextarc = G.vertices[i].fristarrc;
    G.vertices[i].fristarrc = p1; //将新节点*p1插入vi的边表

    ArcNode *p2 = new ArcNode; //生成另一个对称的新的边结点*p2
    p2->adjvex = i; //邻接点序号为i
    p2->nextarc = G.vertices[j].fristarrc;
    G.vertices[j].fristarrc = p2; //将新结点*p2插入顶点Vj的边表

    }
    }

    void CreateUDN(ALGraph &G) { //采用邻接表表示法,创建无向网G

    int i, k;

    cout << "请输入总顶点数和总边数:" ; //输出总顶点数,总边数
    cin >> G.vexnum >> G.arcnum;
    cout << endl;

    cout << "请输入顶点:" << endl;
    for (i = 0 ; i < G.vexnum; i++) { //输入各点,构建表头结点
    cout << "请输入第" << (i + 1) << "个顶点的名称:";
    cin >> G.vertices[i].data;
    G.vertices[i].fristarrc = NULL; //初始化表头结点的指针域为NULL
    }

    cout << endl;
    cout << "请输入一条边依附的顶点,和权值" <<endl;
    for (k = 0; k < G.arcnum; k++) {
    VerTexType v1, v2;
    int i, j,weight;
    cout << "请输入第" << (k+1) << "条边依附的顶点";
    cin >> v1 >> v2>>weight; //输入一条边依附的两个顶点
    i = LocateVex(G, v1); //确定v1和v2在G中的位置,
    j = LocateVex(G, v2); //即顶点在G.vertices(邻接表)中的序号

    ArcNode *p1 = new ArcNode; //生成一个新的边结点*p1
    p1->adjvex = j;
    p1->info = weight; //邻接点序号为j
    p1->nextarc = G.vertices[i].fristarrc;
    G.vertices[i].fristarrc = p1; //将新节点*p1插入vi的边表

    ArcNode *p2 = new ArcNode; //生成另一个对称的新的边结点*p2
    p2->adjvex = i;
    p2->info = weight; //邻接点序号为i
    p2->nextarc = G.vertices[j].fristarrc;
    G.vertices[j].fristarrc = p2; //将新结点*p2插入顶点Vj的边表

    }
    }

    void DepthFS(ALGraph G,int pos){ /*深度优先搜索for图*/
    ArcNode *p=NULL;
    int i = 0,j = 0;
    if(IsRead[pos] == 0){
    IsRead[pos] = 1; //被访问过,打卡
    printf("遍历顶点%c\n",G.vertices[pos].data);
    p= G.vertices[pos].fristarrc; //指向依赖该点的边。边又有三个域:邻接点的位置,权重,指向下一条边的指针。
    }

    while(p!=NULL){
    if(!IsRead[p->adjvex]){
    DepthFS(G,p->adjvex);
    }
    p=p->nextarc;
    }
    }

    void BFS(ALGraph G,int pos){ //广度优先搜索for图
    int i = 0,temp;
    ArcNode * p = NULL;
    queue<char>Q;

    for(i = 0; i <G.vexnum;i++){ //清零
    IsRead[i] = 0;
    }

    if(IsRead[pos] ==0){
    IsRead[pos] = 1;
    printf("遍历顶点:%c\n",G.vertices[pos].data);
    }

    Q.push(pos);
    while(!Q.empty()){ //当队列不为空
    temp=Q.front();
    Q.pop();
    p=G.vertices[temp].fristarrc;
    while(p)
    {
    if(!IsRead[p->adjvex])
    {
    IsRead[p->adjvex]=true;
    printf("遍历顶点:%c\n",G.vertices[p->adjvex].data);
    Q.push(p->adjvex);
    }
    p=p->nextarc;
    }
    }
    }

    int main(){
    ALGraph G;
    CreateUDG(G);

    int i;
    cout << endl;
    for (i = 0; i < G.vexnum; i++) {
    VNode temp = G.vertices[i]; //将G的顶点信息付给temp
    ArcNode *p = temp.fristarrc; //将顶点信息temp中的边信息给p
    if ( p == NULL){
    cout << G.vertices[i].data;
    cout << endl;
    }
    else {
    cout << temp.data;
    while (p)
    {
    cout << "->";
    cout << p->adjvex;
    p = p->nextarc;

    }
    // if(!p){
    // cout<<"->^";
    // }
    }
    cout << endl;
    }
    cout<<"深度遍历:"<<endl;
    DepthFS(G,0);
    cout<<"广度遍历:"<<endl;
    BFS(G,0);
    return 0;
    }

------------- Thank you for reading -------------

Title - Artist
0:00