第十二周项目2——操作用邻接表存储的图

本文介绍了一种基于邻接表存储结构的图算法实现,包括计算顶点出度、找出最大出度顶点、统计出度为0的顶点数量及判断特定边的存在性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

  1. 问题:

    [cpp]  view plain  copy
      在CODE上查看代码片 派生到我的代码片
    1. /*     
    2. * Copyright (c)2016,烟台大学计算机与控制工程学院     
    3. * All rights reserved.     
    4. * 文件名称:项目2.cpp     
    5. * 作    者:梁凯     
    6. * 完成日期:2016年11月16日     
    7. * 版 本 号:v1.0      
    8. *问题描述:假设图G采用邻接表存储,分别设计实现以下要求的算法:  
    9.   (1)输出出图G中每个顶点的出度;  
    10.   (2)求出图G中出度最大的一个顶点,输出该顶点编号;  
    11.   (3)计算图G中出度为0的顶点数;  
    12.   (4)判断图G中是否存在边<i,j>。  
    13.    
    14. *输入描述:无     
    15. *程序输出:测试数据     
    16. */     

  2. 头文件graph.h以及其函数功能实现详见图算法库

    源文件main.cpp代码:


    #include "graph.h"  
  3.   
  4. //返回图G中编号为v的顶点的出度  
  5. int OutDegree(ALGraph *G,int v)  
  6. {  
  7.     ArcNode *p;  
  8.     int n=0;  
  9.     p=G->adjlist[v].firstarc;  
  10.     while (p!=NULL)  
  11.     {  
  12.         n++;  
  13.         p=p->nextarc;  
  14.     }  
  15.     return n;  
  16. }  
  17.   
  18. //输出图G中每个顶点的出度  
  19. void OutDs(ALGraph *G)  
  20. {  
  21.     int i;  
  22.     for (i=0; i<G->n; i++)  
  23.         printf("  顶点%d:%d\n",i,OutDegree(G,i));  
  24. }  
  25.   
  26. //输出图G中出度最大的一个顶点  
  27. void OutMaxDs(ALGraph *G)  
  28. {  
  29.     int maxv=0,maxds=0,i,x;  
  30.     for (i=0; i<G->n; i++)  
  31.     {  
  32.         x=OutDegree(G,i);  
  33.         if (x>maxds)  
  34.         {  
  35.             maxds=x;  
  36.             maxv=i;  
  37.         }  
  38.     }  
  39.     printf("顶点%d,出度=%d\n",maxv,maxds);  
  40. }  
  41. //输出图G中出度为0的顶点数  
  42. void ZeroDs(ALGraph *G)  
  43. {  
  44.     int i,x;  
  45.     for (i=0; i<G->n; i++)  
  46.     {  
  47.         x=OutDegree(G,i);  
  48.         if (x==0)  
  49.             printf("%2d",i);  
  50.     }  
  51.     printf("\n");  
  52. }  
  53.   
  54. //返回图G中是否存在边<i,j>  
  55. bool Arc(ALGraph *G, int i,int j)  
  56. {  
  57.     ArcNode *p;  
  58.     bool found = false;  
  59.     p=G->adjlist[i].firstarc;  
  60.     while (p!=NULL)  
  61.     {  
  62.         if(p->adjvex==j)  
  63.         {  
  64.             found = true;  
  65.             break;  
  66.         }  
  67.         p=p->nextarc;  
  68.     }  
  69.     return found;  
  70. }  
  71.   
  72. int main()  
  73. {  
  74.     ALGraph *G;  
  75.     int A[7][7]=  
  76.     {  
  77.         {0,1,1,1,0,0,0},  
  78.         {0,0,0,0,1,0,0},  
  79.         {0,0,0,0,1,1,0},  
  80.         {0,0,0,0,0,0,1},  
  81.         {0,0,0,0,0,0,0},  
  82.         {0,0,0,1,1,0,1},  
  83.         {0,1,0,0,0,0,0}  
  84.     };  
  85.     ArrayToList(A[0], 7, G);  
  86.     printf("(1)各顶点出度:\n");  
  87.     OutDs(G);  
  88.     printf("(2)最大出度的顶点信息:");  
  89.     OutMaxDs(G);  
  90.     printf("(3)出度为0的顶点:");  
  91.     ZeroDs(G);  
  92.     printf("(4)边<2,6>存在吗?");  
  93.     if(Arc(G,2,6))  
  94.         printf("是\n");  
  95.     else  
  96.         printf("否\n");  
  97.     printf("\n");  
  98.     return 0;  
  99. }  

运行结果:


### 创建实现DFS和BFS 为了在C语言中创建实现深度优先搜索(DFS)和广度优先搜索(BFS),可以采用两种不同的方式来表示的数据结构:邻接矩阵和十字链表。 #### 邻接矩阵表示法 邻接矩阵是一种二维数组,用于表示中的边。对于无向而言,如果存在一条连接顶点`i`到顶点`j`的边,则设置`matrix[i][j]=1`;反之则设为0。有向的情况与此相似,只是方向性决定了哪一端被置位[^1]。 ```c #define MAX_VEX 100 // 假定最大顶点数量不超过此值 typedef struct { char vexs[MAX_VEX]; /* 存储顶点信息 */ int matrix[MAX_VEX][MAX_VEX];/* 邻接矩阵 */ int vexnum, arcnum; /* 当前实际存在的顶点数目和弧的数量 */ } MGraph; ``` #### 十字链表表示法 十字链表是另一种有效的形数据结构表达形式,它不仅能够很好地支持稀疏,而且便于动态增删操作。每个节点由五个部分组成——指向下一个同列节点指针、下一行节点指针、入边标志、出边标志以及该位置上的权重或其它属性字段[^2]。 ```c // 定义边结点EdgeNode 和头结点头HeadNode 结构体 typedef struct EdgeNode{ int adjvex; /* 边所依附的另一个顶点的位置 */ struct EdgeNode *next; /* 指向下一条边的指针 */ }; typedef struct HeadNode{ char data; /* 数据域 */ struct EdgeNode *firstedge;/* 表示第一条依附于该顶点的边 */ }* PtrToAdjList; typedef struct GraphAdjList{ PtrToAdjList adjlist[MAX_VEX]; int n,e; /* 中当前顶点数n和边数e */ } ALGraph; ``` #### 实现DFS递归版本 当使用邻接矩阵作为底层存储机制时,可以通过简单的函数调用来完成递归式的DFS: ```c void DFS(MGraph g,int v){ printf("%d ",g.vexs[v]); visited[v]=true; for(int w=FirstNeighbor(g,v);w>=0;w=NextNeighbor(g,v,w)){ if(!visited[w]){ DFS(g,w); } } } ``` 而对于基于十字链表构建的来说,由于其内部采用了链式列表的形式保存相邻关系,因此需要稍微调整上述逻辑以适应新的遍历模式[^3]。 ```c void DFS(ALGraph G,int k){ EdgeNode* p=G.adjlist[k]->firstedge; Visited[k]=TRUE; VisitFunc(G,k); while(p!=NULL){ if(Visited[p->adjvex]==FALSE){ DFS(G,p->adjvex); } p=p->next; } } ``` #### BFS非递归版 无论是哪种类型的,在执行宽度优先搜索之前都需要先初始化一个队列,并将起始顶点加入其中。之后不断取出队首元素进行处理直至为空为止。这里给出针对邻接矩阵的具体做法如下所示: ```c void BFSTraverse(MGraph G){ Queue Q=(Queue)malloc(sizeof(Queue)); InitQueue(&Q); memset(vis,false,sizeof(bool)*G.n); for(int i=0;i<G.n;++i){ if(!vis[i]){ Enqueue(&Q,i); vis[i]=true; while(!IsEmpty(&Q)){ Dequeue(&Q,&u); ProcessVertex(u); for(w=FirstAdjVex(G,u);w!=-1;w=NextAdjVex(G,u,w)){ if(!vis[w]){ AddTwins(); Enqueue(&Q,w); vis[w]=true; } } } } } } ``` 同样的道理也可以应用于十字链表上,只需修改获取邻居的方式即可。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值