邻接表-数组实现+深搜广搜(超详细)

图的邻接表存储与访问数组实现算法分析

图的存储结构有两种,基于数组的邻接矩阵存储和基于链表的邻接表存储。邻接矩阵存储比较容易实现,但需要很大的内存来存储,访问的时间复杂度高。基于链表的邻接表时间复杂度和空间复杂度比前者要小,但是难于实现。邻接表的数组实现方法综和了以上两种存储方法的优点,在时间复杂度和空间杂度上更优,并且易于理解和实现。

图的邻接矩阵存储,时间复杂度为o(n2),n是图中结点的个数,邻接表的时间复杂度是o(m),m是图边的个数。在最坏的情况下m=(n)*(n-1),但通常图的边远远小于n2,所以时间复杂度比邻接矩阵要优很多。
2.邻接表的数组实现
2.1算法思想
说明:
图上有n个顶点,m条边。每条边都有一个头顶点和尾顶点。头顶点指向此边,尾顶点指向此边的下一条边,如图一所示,边AB是一条以顶点A为头顶点,以顶点B为尾顶点的边。
在这里插入图片描述
实现此算法,首先要借助一个结构体SIDE来存储图中边的信息,内部包含tailNode、nextSide、weight。tailNode表示尾顶点;nextSide表示为有同一头顶点的下一条边的位置,此位置为记录边的结构体edge数组的下标;Weight在带权图中表示一条边的权值,可根据情景加或不加。在图一中,顶点A是AB、AD的头顶点,边AB的结构体中的nextSide可表示为边AD所在的下标位置,tailNode为顶点B。对应的AB边所在的位置由顶点A指出。
此处需要一个head数组,来存储其位置。它的作用是存储头顶点指向的第一条边的下标位置。那么A顶点所指向的第二条边的位置就由第一条边的nextSide指出,以此类推。
具体实现过程:
先输入顶点个数,边的个数,再将head数组赋初值为-1,表示图中的每一个顶点指向的边都为空。然后再输入每一条边头尾顶点。根据头尾顶点创建边,将边信息存于edeg结构体数组中。具体做法为:实现CreateABoundary函

<think>嗯,用户想了解如何用C语言实现邻接矩阵的DFS和BFS。首先,我需要回顾一下邻接矩阵的基本结构。邻接矩阵是一个二维数组,其中元素表示顶点之间是否有边。比如,如果顶点i和j之间有边,那么矩阵的arr[i][j]就是1或者权重,否则可能是0或者无穷大。 然后,DFS和BFS的实现方法。DFS通常用递归或者栈来实现,而BFS用队列。记得要维护一个visited数组,记录哪些顶点已经被访问过,避免重复访问。 接下来,我需要参考用户提供的引用内容。引用[4]里提到了一些代码片段,比如辅助数组visited[MVNUM],以及递归函数dfsAM。这可能是一个DFS的实现。同时,引用[2]提到邻接矩阵的存储和DFS、BFS的实现,其中DFS有两种方式,其中一种和BFS类似,只是用栈代替队列。不过用户需要的是C语言示例,而引用[2]中的代码是C++的,需要注意转换。 用户需要具体的示例代码,所以得构造一个完整的C程序。首先定义邻接矩阵的结构。比如,用结构体包含顶点表、邻接矩阵、顶点数和边数。然后初始化的函数,创建顶点和边。 对于DFS的实现,递归方法比较直观。从起始顶点开始,标记为已访问,然后遍历所有邻接顶点,递归访问未访问过的顶点。注意循环遍历所有可能的邻接点,检查邻接矩阵中的值是否为有效边,并且未被访问过。 BFS的话,需要使用队列。C语言没有内置队列,需要自己实现或者用数组模拟。这里可能需要一个循环队列,维护front和rear指针。将起始顶点入队,标记为已访问,然后出队,访问其邻接顶点,将未访问的入队,并标记。重复直到队列为空。 需要处理的连通性问题吗?比如,如果不是连通的,可能需要遍历所有顶点,检查是否被访问过,然后从每个未访问的顶点开始DFS或BFS。但用户的问题可能只需要基本的连通处理,所以示例代码可能只处理从指定顶点开始的情况。 另外,注意代码中的MAXINT定义,可能表示无穷大,即没有边的情况。比如,在邻接矩阵中,如果arr[i][j]等于MAXINT,则i和j之间没有边。 测试部分,可能需要创建一个的实例,比如添加顶点A、B、C等,然后添加边,最后调用DFS和BFS函数。 现在,将所有这些整合到一个完整的C代码示例中。确保代码正确,没有语法错误,比如函数声明、结构体定义、队列的实现是否正确。 可能遇到的问题:队列的大小是否足够,递归度是否会导致栈溢出,但示例代码可能不需要处理大规模数据,所以暂时忽略。 最后,检查是否满足用户的所有要求:邻接矩阵、DFS和BFS的C语言实现,代码正确性,结构清晰,注释说明。</think>### C语言实现邻接矩阵的DFS和BFS #### 1. 邻接矩阵结构定义 邻接矩阵使用二维数组存储顶点间边的信息: ```c #define MAX_VERTEX 10 //最大顶点数 #define MAXINT 32767 //表示无穷大(无连接) typedef struct { char vexs[MAX_VERTEX]; //顶点表 int arr[MAX_VERTEX][MAX_VERTEX]; //邻接矩阵 int vexnum, edgenum; //顶点数和边数 } AMGraph; ``` #### 2. 初始化邻接矩阵 ```c //创建无向示例 void CreateAMGraph(AMGraph *G) { G->vexnum = 5; //假设5个顶点A,B,C,D,E G->edgenum = 6; //假设6条边 //顶点表赋值 for (int i=0; i<5; i++) G->vexs[i] = 'A' + i; //初始化邻接矩阵 for (int i=0; i<MAX_VERTEX; i++) for (int j=0; j<MAX_VERTEX; j++) G->arr[i][j] = MAXINT; //添加边(示例) int edges[6][2] = {{0,1}, {0,2}, {1,3}, {2,3}, {3,4}, {2,4}}; for (int i=0; i<6; i++) { int v1 = edges[i][0], v2 = edges[i][1]; G->arr[v1][v2] = 1; //无向对称赋值 G->arr[v2][v1] = 1; } } ``` #### 3. 度优先索(DFS)实现 使用递归实现DFS[^4]: ```c int visited[MAX_VERTEX] = {0}; //访问标记数组 void DFS(AMGraph G, int i) { printf("%c ", G.vexs[i]); visited[i] = 1; for (int j=0; j<G.vexnum; j++) { if (G.arr[i][j]!=MAXINT && !visited[j]) { DFS(G, j); } } } //调用示例:DFS(*G, 0); 从A开始遍历 ``` #### 4. 广度优先索(BFS)实现 使用循环队列实现BFS[^2]: ```c #define QUEUE_SIZE 20 int queue[QUEUE_SIZE]; int front=0, rear=0; void BFS(AMGraph G, int start) { printf("%c ", G.vexs[start]); visited[start] = 1; queue[rear++] = start; while (front != rear) { int current = queue[front++]; front %= QUEUE_SIZE; for (int j=0; j<G.vexnum; j++) { if (G.arr[current][j]!=MAXINT && !visited[j]) { printf("%c ", G.vexs[j]); visited[j] = 1; queue[rear++] = j; rear %= QUEUE_SIZE; } } } } //调用示例:BFS(G, 0); ``` #### 5. 完整测试代码 ```c #include <stdio.h> int main() { AMGraph G; CreateAMGraph(&G); printf("DFS: "); DFS(G, 0); //重置visited数组 for (int i=0; i<MAX_VERTEX; i++) visited[i]=0; printf("\nBFS: "); BFS(G, 0); return 0; } ``` #### 6. 输出示例 ``` DFS: A B D E C BFS: A B C D E ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值