鱼C论坛

 找回密码
 立即注册
查看: 2325|回复: 4

[已解决]C语言bfs寻找最短路径

[复制链接]
发表于 2023-4-18 17:09:29 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

x
不是要显示距离,要把怎么走的显示出来,求助!!!
最佳答案
2023-4-18 18:19:46
代码:
  1. #include <stdio.h>
  2. #include <stdbool.h>

  3. #define MAXN 100 // 最大节点数
  4. #define INF 0x3f3f3f3f // 无穷大

  5. int n, m; // n为节点数,m为边数
  6. int G[MAXN][MAXN]; // 邻接矩阵
  7. int dist[MAXN]; // 距离数组
  8. int pre[MAXN]; // 前驱节点数组
  9. bool visited[MAXN]; // 标记数组

  10. void bfs(int s) {
  11.     for (int i = 0; i < n; i++) {
  12.         dist[i] = INF; // 初始化距离数组
  13.         pre[i] = -1; // 初始化前驱节点数组
  14.         visited[i] = false; // 初始化标记数组
  15.     }
  16.     dist[s] = 0; // 起点距离为0
  17.     visited[s] = true; // 起点已经访问过
  18.     int q[MAXN], front = 0, rear = 0; // 队列及其指针
  19.     q[rear++] = s; // 起点入队
  20.     while (front < rear) { // 队列非空
  21.         int u = q[front++]; // 取出队首节点
  22.         for (int v = 0; v < n; v++) { // 遍历u的邻接点
  23.             if (G[u][v] != INF && !visited[v]) { // 如果v是u的邻接点且未访问过
  24.                 dist[v] = dist[u] + 1; // 更新v的距离
  25.                 pre[v] = u; // 设置v的前驱节点为u
  26.                 visited[v] = true; // 标记v已经访问过
  27.                 q[rear++] = v; // v入队
  28.             }
  29.         }
  30.     }
  31. }

  32. void print_path(int s, int t) {
  33.     if (s == t) { // 如果起点和终点相同,直接输出起点
  34.         printf("%d", s);
  35.         return;
  36.     }
  37.     int path[MAXN], top = 0; // 路径数组及其指针
  38.     for (int u = t; u != -1; u = pre[u]) { // 从终点往前遍历前驱节点
  39.         path[top++] = u; // 将节点加入路径数组
  40.     }
  41.     for (int i = top - 1; i >= 0; i--) { // 输出路径上的节点
  42.         printf("%d", path[i]);
  43.         if (i > 0) printf("->");
  44.     }
  45. }

  46. int main() {
  47.     scanf("%d%d", &n, &m);
  48.     for (int i = 0; i < n; i++) {
  49.         for (int j = 0; j < n; j++) {
  50.             G[i][j] = INF; // 初始化邻接矩阵
  51.         }
  52.     }
  53.     while (m--) {
  54.         int u, v;
  55.         scanf("%d%d", &u, &v);
  56.         G[u][v] = G[v][u] = 1; // 无向图,两个方向都要设置
  57.     }
  58.     int s, t;
  59.     scanf("%d%d", &s, &t);
  60.     bfs(s);
  61.     printf("Shortest path from %d to %d: ", s, t);
  62.     print_path(s, t);
  63.     printf("\n");
  64.     return 0;
  65. }
复制代码


                               
登录/注册后可看大图


                               
登录/注册后可看大图
小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

发表于 2023-4-18 17:14:39 | 显示全部楼层
本帖最后由 歌者文明清理员 于 2023-4-18 17:18 编辑

以下是C语言实现BFS寻找最短路径并将路径显示出来的示例代码:

  1. #include <stdio.h>
  2. #define MAX_N 100

  3. int map[MAX_N][MAX_N];   // 存储地图的邻接矩阵
  4. int pre[MAX_N];          // 存储每个节点的前驱节点
  5. int visited[MAX_N];      // 记录节点是否已经被访问过

  6. typedef struct queue{
  7.     int data[MAX_N];
  8.     int head, tail;
  9. } Queue;

  10. // 初始化队列
  11. void initQueue(Queue *q){
  12.     q->head = q->tail = 0;
  13. }

  14. // 入队
  15. void enqueue(Queue *q, int value){
  16.     q->data[q->tail++] = value;
  17. }

  18. // 出队
  19. int dequeue(Queue *q){
  20.     return q->data[q->head++];
  21. }

  22. // BFS遍历,查找最短路径
  23. int bfs(int n, int start, int end){
  24.     Queue q;
  25.     initQueue(&q);
  26.     visited[start] = 1;  // 将起点标记为访问过
  27.     enqueue(&q, start);  // 将其加入队列

  28.     while (q.head != q.tail){  // 判断队列是否为空
  29.         int cur = dequeue(&q);  // 将队首元素出队
  30.         if (cur == end) break;  // 找到了终点,退出循环

  31.         for (int i=1; i<=n; i++){
  32.             // 如果当前节点与i相邻且i没有被访问过
  33.             if (map[cur][i]==1 && visited[i]==0){
  34.                 visited[i] = 1;     // 标记为访问过
  35.                 pre[i] = cur;        // 记录i的前驱节点是cur
  36.                 enqueue(&q, i);      // 将i加入队列
  37.             }
  38.         }
  39.     }

  40.     // 构造路径
  41.     int path[MAX_N];
  42.     int len = 0;
  43.     while (end != start){
  44.         path[len++] = end;  // 将当前节点加入路径数组
  45.         end = pre[end];     // 更新为前驱节点
  46.     }
  47.     path[len++] = start;    // 将起点加入数组

  48.     // 输出路径
  49.     for (int i=len-1; i>=0; i--){
  50.         printf("%d ", path[i]);
  51.     }
  52.     printf("\n");

  53.     return len - 1;  // 返回路径长度
  54. }

  55. int main(){
  56.     int n, m;
  57.     scanf("%d%d", &n, &m);

  58.     // 读入地图信息,构造邻接矩阵
  59.     for (int i=1; i<=m; i++){
  60.         int a, b;
  61.         scanf("%d%d", &a, &b);
  62.         map[a][b] = map[b][a] = 1;
  63.     }

  64.     int start, end;
  65.     scanf("%d%d", &start, &end);

  66.     printf("最短路径是:");
  67.     bfs(n, start, end);

  68.     return 0;
  69. }
复制代码


说明:
  • map 是一个二维数组,用于存储地图的邻接矩阵。如果map[i ][j]为1,则表示第i个节点与第j个节点相邻;否则表示不相邻。
  • pre 是一个一维数组,用于存储每个节点的前驱节点。在BFS过程中,如果发现节点i的前驱节点是节点j,则将 pre[i ]设为j。
  • visited 是一个一维数组,用于记录每个节点是否已经被访问过。初始时,将起点标记为已访问过。
  • Queue 是一个结构体,包含一个整型数组和两个指针 head、tail,分别指向队列头部和尾部。initQueue 函数用于初始化队列,enqueue 函数用于入队,dequeue 函数用于出队。在本示例中,我们采用数组实现队列。
  • 在 BFS 过程中,我们从起点开始遍历地图,将访问过的节点加入队列。在遍历过程中,我们记录每个节点的前驱节点,直到找到了终点或队列为空。如果找到了终点,则构造路径并输出。


注意事项:
  • 本示例中,在构造路径时使用了逆序输出方式。具体来说,我们先将终点加入路径数组,然后沿着前驱节点逐步往回推导,最终得到完整路径,并按照从起点到终点的顺序输出。
  • 本示例中没有考虑输入数据是否合法,比如节点编号是否越界、起点和终点是否为同一节点等。在实际编程中,建议添加相应的输入检查处理。
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2023-4-18 17:17:16 | 显示全部楼层
以下是一个基本的C语言实现,使用广度优先搜索(BFS)来找到并显示无向图中两个顶点之间的最短路径。这个实现假定您已经使用了一个邻接表来表示图。

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <stdbool.h>

  4. #define MAX_NODES 100

  5. typedef struct Queue {
  6.     int items[MAX_NODES];
  7.     int front;
  8.     int rear;
  9. } Queue;

  10. Queue* createQueue();
  11. void enqueue(Queue* q, int value);
  12. int dequeue(Queue* q);
  13. int isEmpty(Queue* q);

  14. void bfs(int start, int target, int num_nodes, int adj[][num_nodes], int path[]);

  15. int main() {
  16.     int num_nodes, num_edges;
  17.     printf("Enter the number of nodes and edges: ");
  18.     scanf("%d%d", &num_nodes, &num_edges);

  19.     int adj[num_nodes][num_nodes];
  20.     for (int i = 0; i < num_nodes; i++) {
  21.         for (int j = 0; j < num_nodes; j++) {
  22.             adj[i][j] = 0;
  23.         }
  24.     }

  25.     printf("Enter the edges:\n");
  26.     for (int i = 0; i < num_edges; i++) {
  27.         int u, v;
  28.         scanf("%d%d", &u, &v);
  29.         adj[u][v] = adj[v][u] = 1;
  30.     }

  31.     int start, target;
  32.     printf("Enter the starting and target nodes: ");
  33.     scanf("%d%d", &start, &target);

  34.     int path[MAX_NODES];
  35.     for (int i = 0; i < MAX_NODES; i++) {
  36.         path[i] = -1;
  37.     }

  38.     bfs(start, target, num_nodes, adj, path);

  39.     printf("Shortest Path: ");
  40.     if (path[target] != -1) {
  41.         int node = target;
  42.         while (node != start) {
  43.             printf("%d <- ", node);
  44.             node = path[node];
  45.         }
  46.         printf("%d\n", start);
  47.     } else {
  48.         printf("No path found.\n");
  49.     }

  50.     return 0;
  51. }

  52. Queue* createQueue() {
  53.     Queue* q = (Queue*)malloc(sizeof(Queue));
  54.     q->front = -1;
  55.     q->rear = -1;
  56.     return q;
  57. }

  58. void enqueue(Queue* q, int value) {
  59.     if (q->rear == MAX_NODES - 1)
  60.         return;
  61.     else {
  62.         if (q->front == -1)
  63.             q->front = 0;
  64.         q->rear++;
  65.         q->items[q->rear] = value;
  66.     }
  67. }

  68. int dequeue(Queue* q) {
  69.     int item;
  70.     if (isEmpty(q)) {
  71.         item = -1;
  72.     } else {
  73.         item = q->items[q->front];
  74.         q->front++;
  75.         if (q->front > q->rear) {
  76.             q->front = q->rear = -1;
  77.         }
  78.     }
  79.     return item;
  80. }

  81. int isEmpty(Queue* q) {
  82.     return q->rear == -1;
  83. }

  84. void bfs(int start, int target, int num_nodes, int adj[][num_nodes], int path[]) {
  85.     Queue* q = createQueue();
  86.     bool visited[num_nodes];

  87.     for (int i = 0; i < num_nodes; i++) {
  88.         visited[i] = false;
  89.     }

  90.     visited[start] = true;
  91.     enqueue(q, start);

  92.     while (!isEmpty(q)) {
  93.         int current = dequeue(q);

  94.         for (int i = 0; i < num_nodes; i++) {
  95.             if (adj[current][i] && !visited[i]) {
  96.                 visited[i] = true;
  97.                 enqueue(q, i);
  98.                 path[i] = current;
  99.                 if (i == target) {
  100.                     break;
  101.                 }
  102.             }
  103.         }
  104.     }
  105.     free(q);
  106. }
复制代码



这个程序首先读取节点和边的数量,并初始化一个邻接矩阵。然后,它从用户处获取边和起始节点、目标节点的信息。最后,它使用BFS算法找到最短路径,并将其打印出来。

请注意,此实现仅适用于无向图,并且不支持带有权重的边。对于有向图和带权重的边的图,请考虑使用其他算法,如Dijkstra算法。
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2023-4-18 18:19:46 | 显示全部楼层    本楼为最佳答案   
代码:
  1. #include <stdio.h>
  2. #include <stdbool.h>

  3. #define MAXN 100 // 最大节点数
  4. #define INF 0x3f3f3f3f // 无穷大

  5. int n, m; // n为节点数,m为边数
  6. int G[MAXN][MAXN]; // 邻接矩阵
  7. int dist[MAXN]; // 距离数组
  8. int pre[MAXN]; // 前驱节点数组
  9. bool visited[MAXN]; // 标记数组

  10. void bfs(int s) {
  11.     for (int i = 0; i < n; i++) {
  12.         dist[i] = INF; // 初始化距离数组
  13.         pre[i] = -1; // 初始化前驱节点数组
  14.         visited[i] = false; // 初始化标记数组
  15.     }
  16.     dist[s] = 0; // 起点距离为0
  17.     visited[s] = true; // 起点已经访问过
  18.     int q[MAXN], front = 0, rear = 0; // 队列及其指针
  19.     q[rear++] = s; // 起点入队
  20.     while (front < rear) { // 队列非空
  21.         int u = q[front++]; // 取出队首节点
  22.         for (int v = 0; v < n; v++) { // 遍历u的邻接点
  23.             if (G[u][v] != INF && !visited[v]) { // 如果v是u的邻接点且未访问过
  24.                 dist[v] = dist[u] + 1; // 更新v的距离
  25.                 pre[v] = u; // 设置v的前驱节点为u
  26.                 visited[v] = true; // 标记v已经访问过
  27.                 q[rear++] = v; // v入队
  28.             }
  29.         }
  30.     }
  31. }

  32. void print_path(int s, int t) {
  33.     if (s == t) { // 如果起点和终点相同,直接输出起点
  34.         printf("%d", s);
  35.         return;
  36.     }
  37.     int path[MAXN], top = 0; // 路径数组及其指针
  38.     for (int u = t; u != -1; u = pre[u]) { // 从终点往前遍历前驱节点
  39.         path[top++] = u; // 将节点加入路径数组
  40.     }
  41.     for (int i = top - 1; i >= 0; i--) { // 输出路径上的节点
  42.         printf("%d", path[i]);
  43.         if (i > 0) printf("->");
  44.     }
  45. }

  46. int main() {
  47.     scanf("%d%d", &n, &m);
  48.     for (int i = 0; i < n; i++) {
  49.         for (int j = 0; j < n; j++) {
  50.             G[i][j] = INF; // 初始化邻接矩阵
  51.         }
  52.     }
  53.     while (m--) {
  54.         int u, v;
  55.         scanf("%d%d", &u, &v);
  56.         G[u][v] = G[v][u] = 1; // 无向图,两个方向都要设置
  57.     }
  58.     int s, t;
  59.     scanf("%d%d", &s, &t);
  60.     bfs(s);
  61.     printf("Shortest path from %d to %d: ", s, t);
  62.     print_path(s, t);
  63.     printf("\n");
  64.     return 0;
  65. }
复制代码


                               
登录/注册后可看大图


                               
登录/注册后可看大图
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2023-4-19 08:51:40 | 显示全部楼层
我去,這ChatGPT出了大力了
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2025-6-10 17:40

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表