• C语言数据结构之图的基本操作


    本博文是是博主在学习数据结构图的这一章知识时做的一些总结,代码运行环境:visual studio2017 纯C语言 ,当然掌握了方法,你也可以试着用其它的语言来实现同样的功能。

    下面的程序主要实现了对有向图,有向网,无向图,无向网,无向图的深度优先遍历,广度优先遍历,有向无环图的拓扑排序功能等。

    主要代码实现如下:

      1 #pragma once
      2 #include<stdio.h>
      3 #include"stdlib.h"
      4 #define ElemType char
      5 #define MAXQSIZE 50
      6 #define INFINITY INT_MAX
      7 #define MAX_VERTEX_NUM 20
      8 typedef enum { DG, DN, UDG, UDN } GraphKind;
      9 typedef struct ArcCell {
     10     int adj;         //顶点关系类型 对于无权图 用0或1表示
     11                      //char *info;     //弧相关信息的指针
     12 }ArcCell, AdjMatrix[MAX_VERTEX_NUM][MAX_VERTEX_NUM];
     13 typedef struct {
     14     char vers[MAX_VERTEX_NUM];  //用一个字符数组存储顶点向量
     15     AdjMatrix arcs;            //邻接矩阵
     16     int vexnum, arcnum;         //图的当前顶点数和弧数 
     17     GraphKind kind;               //图的种类标志
     18     int in[MAX_VERTEX_NUM];  //存放所有节点的入度
     19 }MGraph;
     20 //图G中顶点v的第一个邻接点,不存在时返回 -1 
     21 int FirstAdjVex(MGraph&G, int v)
     22 {
     23 
     24     int i;
     25     for (i = 0; i < G.vexnum; i++)
     26     {
     27         if (G.arcs[v][i].adj)
     28         {
     29             return i;
     30         }
     31     }
     32     return -1;
     33 }
     34 //图G中顶点v在w之后的下一个邻接点,不存在时返回 -1
     35 int NextAdjVex(MGraph G, int v, int w)
     36 {
     37 
     38     int i;
     39     for (i = w + 1; i < G.vexnum; i++)
     40     {
     41         if (G.arcs[v][i].adj)
     42         {
     43             return i;
     44         }
     45     }
     46     return -1;
     47 
     48 }
     49 //深度优先遍历图
     50 bool visited[MAX_VERTEX_NUM];
     51 void DFS(MGraph G, int v)
     52 {
     53     visited[v] = true;
     54     printf("%c", G.vers[v]);
     55     int j;
     56     for (j = 1; j <= G.vexnum; j++) {
     57         if (visited[j] == 0 && G.arcs[v][j].adj == 1)
     58         {
     59             DFS(G, j);//v每循环一次值都会变 上一轮的j值赋给了v
     60         }
     61     }
     62 }
     63 
     64 //广度优先遍历
     65 int BFSTraverse(MGraph G, int s)
     66 {
     67     //清空访问标志  
     68     for (int i = 0; i <MAX_VERTEX_NUM; i++)
     69         visited[i] = false;
     70     //定义队列,用于保存当前节点的邻接顶点  
     71     int Q[MAX_VERTEX_NUM];
     72     int front = 0;
     73     int rear = 0;
     74     int i, j;
     75     printf("%c", G.vers[s]);
     76     visited[s] = 1;
     77     Q[rear++] = s;
     78     //遍历队列   
     79     while (front < rear)
     80     {
     81         i = Q[front++];
     82         for (j = 1; j <= G.vexnum; j++)
     83         {
     84             if (visited[j] == false && G.arcs[i][j].adj == 1)
     85             {
     86                 printf("%c", G.vers[j]);
     87                 visited[j] = true;
     88                 Q[rear++] = j;
     89             }
     90 
     91         }
     92     }
     93     return 0;
     94 }
     95 
     96 //定位顶点
     97 int LocateVex(MGraph &G, char v)
     98 {
     99     int i;
    100     for (i = 0; i<G.vexnum; i++)
    101     {
    102         if (v == G.vers[i])
    103         {
    104             return i;
    105         }
    106     }
    107     return -1;
    108 
    109 }
    110 
    111 //创建有向图
    112 int CreateDG(MGraph &G) {
    113     int i, j, k;
    114     char v1, v2;
    115     printf("请输入顶点数:");
    116     scanf("%d", &G.vexnum);
    117     printf("
    请输入弧数:");
    118     scanf("%d", &G.arcnum);
    119     printf("请输入%d个顶点:(每个顶点之间用空格隔开)", G.vexnum);
    120     fflush(stdin);
    121     getchar(); //吃掉空格
    122     for (i = 0; i < G.vexnum; i++)
    123     {
    124         scanf("%c", &G.vers[i]);
    125         getchar();  //吃掉空格 注意数组vers[i]的初始大小为20
    126     }
    127     //打印输出各个顶点
    128     for (i = 0; i < G.vexnum; i++)
    129     {
    130         printf("%c", G.vers[i]);
    131 
    132     }
    133     printf("
    ");
    134     for (i = 0; i < G.vexnum; i++)
    135     {
    136         for (j = 0; j < G.vexnum; j++)
    137         {
    138             G.arcs[i][j].adj = INFINITY;
    139 
    140         }
    141     }
    142     //入度初始化
    143     for (int i = 0; i < G.vexnum; i++)
    144     {
    145         G.in[i] = 0;
    146     }
    147     for (k = 0; k < G.arcnum; k++)
    148     {
    149         printf("
    please input <v1 v2>:");
    150         fflush(stdin);
    151         scanf("%c %c", &v1, &v2);  //v1 v2 之间用空格隔开
    152         fflush(stdin);//清除残余后,后面再读入时不会出错
    153         i = LocateVex(G, v1);
    154         j = LocateVex(G, v2);
    155         G.arcs[i][j].adj = 1;
    156         G.in[j]++;
    157         getchar();
    158     }
    159     return 1;
    160 }
    161 
    162 //创建有向网
    163 int CreateDN(MGraph &G) {
    164     int i, j, k, w;
    165     char v1, v2;
    166     printf("请输入顶点数:");
    167     scanf("%d", &G.vexnum);
    168     printf("
    请输入弧的数目:");
    169     scanf("%d", &G.arcnum);
    170     printf("请输入%d个顶点:(每个顶点之间用空格隔开)", G.vexnum);
    171     fflush(stdin);
    172     getchar(); //吃掉空格
    173     for (i = 0; i < G.vexnum; i++)
    174     {
    175         scanf("%c", &G.vers[i]);
    176         getchar();  //吃掉空格 注意数组vers[i]的初始大小为20
    177     }
    178     //打印输出各个顶点
    179     for (i = 0; i < G.vexnum; i++)
    180     {
    181         printf("%c", G.vers[i]);
    182 
    183     }
    184     printf("
    ");
    185     //初始化邻接矩阵
    186     for (i = 0; i < G.vexnum; i++)
    187     {
    188         for (j = 0; j < G.vexnum; j++)
    189         {
    190             G.arcs[i][j].adj = INFINITY;
    191 
    192         }
    193     }
    194     for (k = 0; k < G.arcnum; k++)
    195     {
    196         printf("
     please input <v1 v2 w>:");
    197         fflush(stdin);
    198         scanf("%c %c %d", &v1, &v2, &w);  //v1 v2 w之间用空格隔开
    199         fflush(stdin);//清除残余后,后面再读入时不会出错
    200         i = LocateVex(G, v1);
    201         j = LocateVex(G, v2);
    202         G.arcs[i][j].adj = w;
    203 
    204         getchar();  //吃掉空格
    205     }
    206     return 1;
    207 }
    208 
    209 //创建无向图
    210 int CreateUDG(MGraph &G)
    211 {
    212     int i, j, k;
    213     char v1, v2;
    214     printf("请输入顶点数:");
    215     scanf("%d", &G.vexnum);
    216     printf("
    请输入边数:");
    217     scanf("%d", &G.arcnum);
    218     printf("请输入%d个顶点:(每个顶点之间用空格隔开)", G.vexnum);
    219     fflush(stdin);
    220     getchar(); //吃掉空格
    221     for (i = 0; i < G.vexnum; i++)
    222     {
    223         scanf("%c", &G.vers[i]);
    224         getchar();  //吃掉空格 注意数组vers[i]的初始大小为20
    225     }
    226     //打印输出各个顶点
    227     for (i = 0; i < G.vexnum; i++)
    228     {
    229         printf("%c", G.vers[i]);
    230 
    231     }
    232     printf("
    ");
    233     for (i = 0; i < G.vexnum; i++)
    234     {
    235         for (j = 0; j < G.vexnum; j++)
    236         {
    237             G.arcs[i][j].adj = INFINITY;
    238         }
    239     }
    240     for (k = 0; k < G.arcnum; k++)
    241     {
    242         printf("
    please input <v1 v2>:");
    243         fflush(stdin);
    244         scanf("%c %c", &v1, &v2);  //v1 v2 之间用空格隔开
    245         fflush(stdin);//清除残余后,后面再读入时不会出错
    246         i = LocateVex(G, v1);
    247         j = LocateVex(G, v2);
    248         G.arcs[i][j].adj = 1;
    249         G.arcs[j][i].adj = 1;
    250         getchar();
    251     }
    252     return 1;
    253 }
    254 
    255 //创建无向网
    256 int CreateUDN(MGraph &G)
    257 {
    258     int i, j, k, w;
    259     char v1, v2;
    260     printf("请输入顶点数:");
    261     scanf("%d", &G.vexnum);
    262     printf("
    请输入边的数目:");
    263     scanf("%d", &G.arcnum);
    264     printf("请输入%d个顶点:(每个顶点之间用空格隔开)", G.vexnum);
    265     fflush(stdin);
    266     getchar(); //吃掉空格
    267     for (i = 0; i < G.vexnum; i++)
    268     {
    269         scanf("%c", &G.vers[i]);
    270         getchar();  //吃掉空格 注意数组vers[i]的初始大小为20
    271     }
    272     //打印输出各个顶点
    273     for (i = 0; i < G.vexnum; i++)
    274     {
    275         printf("%c", G.vers[i]);
    276 
    277     }
    278     printf("
    ");
    279     //初始化邻接矩阵
    280     for (i = 0; i < G.vexnum; i++)
    281     {
    282         for (j = 0; j < G.vexnum; j++)
    283         {
    284             G.arcs[i][j].adj = INFINITY;
    285         }
    286     }
    287     for (k = 0; k < G.arcnum; k++)
    288     {
    289         printf("
     please input <v1 v2 w>:");
    290         fflush(stdin);
    291         scanf("%c %c %d", &v1, &v2, &w);  //v1 v2 w之间用空格隔开
    292         fflush(stdin);//清除残余后,后面再读入时不会出错
    293         i = LocateVex(G, v1);
    294         j = LocateVex(G, v2);
    295         G.arcs[i][j].adj = w;
    296         G.arcs[j][i].adj = w;
    297         getchar();  //吃掉空格
    298     }
    299     return 1;
    300 }
    301 //栈类型
    302 typedef int SElemType;
    303 #define STACK_INIT_SIZE1 10                                      //存储空间初始分配量
    304 #define STACKINCREMENT1 2                                        //存储空间分配增量
    305 
    306 //栈的顺序存储结构表示
    307 typedef struct SqStack1
    308 {
    309     SElemType *base;                        //基地址
    310     SElemType *top;                         //栈顶指针
    311     int stacksize1;                          //当前已经分配的存储空间
    312 }SqStack1;
    313 
    314 //构造一个空栈
    315 int InitStack1(SqStack1&S)
    316 {
    317     //为栈底分分配一个指定大小的存储空间
    318     S.base = (SElemType *)malloc(STACK_INIT_SIZE1 * sizeof(SElemType));
    319     if (!S.base)
    320         exit(0);
    321     S.top = S.base;                   //栈底与栈顶指针相同
    322     S.stacksize1 = STACK_INIT_SIZE1;
    323     return 1;
    324 }
    325 
    326 
    327 //若栈S为空栈(栈底指针和栈顶指针相同), 则返回1,否则返回0
    328 int StackEmpty1(SqStack1&S)
    329 {
    330     if (S.top == S.base)
    331         return 1;
    332     else
    333         return 0;
    334 }
    335 
    336 
    337 //插入元素e为新的栈顶元素
    338 int Push(SqStack1 *S, SElemType e)
    339 {
    340     if ((*S).top - (*S).base >= (*S).stacksize1)
    341     {
    342         (*S).base = (SElemType *)realloc((*S).base, ((*S).stacksize1 + STACKINCREMENT1) * sizeof(SElemType));
    343         if (!(*S).base)
    344             exit(0);
    345         (*S).top = (*S).base + (*S).stacksize1;
    346         (*S).stacksize1 += STACKINCREMENT1;
    347     }
    348     *((*S).top)++ = e;
    349     return 1;
    350 }
    351 
    352 
    353 //若栈不为空,则删除S栈顶元素用e返回其值,并返回1,否则返回0
    354 int Pop(SqStack1 *S, SElemType *e)
    355 {
    356     if ((*S).top == (*S).base)
    357     {
    358         return 0;
    359     }
    360     *e = *--(*S).top;
    361     return 1;
    362 }
    363 //有向图的拓扑排序
    364 void TopologicalSort(MGraph G)
    365 {
    366     int i, j,k;
    367     int count = 0;
    368     SqStack1 S;
    369     InitStack1(S);
    370     for (i = 0; i<G.vexnum; i++)
    371     {
    372         if (G.in[i] == 0)
    373         {
    374             Push(&S, i);
    375         }
    376     }
    377     while (!StackEmpty1(S))
    378     {
    379         Pop(&S, &k);
    380         printf("%c->", G.vers[k]);
    381         count++;
    382         for (i = 0; i < G.vexnum; i++)
    383         {
    384             if (G.arcs[k][i].adj == 1)
    385             {
    386                 G.in[i]--;
    387                 if (G.in[i] == 0)
    388                 {
    389                     Push(&S, i);
    390                 }
    391             }
    392         }
    393     }
    394     //如果计算得到的拓扑排序的节点数目小于总的,说明不是连通图
    395     if (count < G.vexnum)
    396     {
    397         printf("此图是有环路的
    ");
    398     }
    399     else
    400     {
    401         printf("此图是没有环路的
    ");
    402     }
    403 
    404 }
  • 相关阅读:
    python-批量执行.py文件
    python-写入excel(xlswriter)
    python-读取excel(xlrd)
    python接口自动化测试-requests.post()
    python-读取配置文件
    python-mysql
    python-Redis的List操作
    python-Redis的String、Hash操作
    Elasitcsearch High Level Rest Client使用示例
    前端并发优化技巧
  • 原文地址:https://www.cnblogs.com/doctorXiong/p/9187087.html
Copyright © 2020-2023  润新知