C语言算法1.1:连通问题【视频解析】

!!!喜欢看视频的朋友请点击这里!!!

一、来源

来自《算法:C语言实现(第1-4部分)第3版》书的程序1.1。


二、什么是连通问题

连通问题就是判断一堆节点中,两个节点是否能连通的问题。场景举例如下:
假如现在某城市要修改地铁站,有4个区分别是A、B、C、D,现在从A到B已经修好了(表明A和B是连通的),从C到D也已经修好了(即C和D也是连通的),那么请问现在张三从A站坐地铁能到达D吗?不能,因为A和D不能连通。
那怎么让A和D连通呢?有多种方案,比如:

  1. 从A站直接修地铁到D站,张三坐车方案:A -> D
  2. 从B站修地铁到D站,张三坐车方案:A -> B -> D
  3. 从B站修地铁到C站,张三坐车方案:A -> B -> C -> D

三、业务场景抽象成代码结构

假设有一个一维数组a,大小为10,a[0]到a[9]中存的值分别为0~9,即每个元素的值都不一样。
程序认为,当a[i]和a[j]的值不一样时,i和j不连通,当两个值一样时,i和j连通。

(感叹一下,真没想到用一个一维数组就给实现了。)
修改版代码有更多注释。


四、原书代码

#include <stdio.h>
#define N 10000
main() {
  int i, p, q, t, id[N];
  for (i = 0; i < N; i++) id[i] = i;
  while (scanf("%d %d\n", &p, &q) == 2) {
    if (id[p] == id[q]) continue;
    for (t = id[p], i = 0; i < N; i++)
      if (id[i] == t) id[i] = id[q];
    printf(" %d %d\n", p, q);
  }
}

五、修改版代码

#include <stdio.h>

/** 常量N,表示数组的大小 */
#define N 10

/**
 * 连通问题:
 * <pre>
 *  1. 连通问题场景举例:
 *      假如现在某城市要修改地铁站,有4个区分别是A、B、C、D,现在从A到B已经修好了(表明A和B是连通的),从C到D也已经修好了(即C和D也是连通的),那么请问现在张三从A站坐地铁能到达D吗?不能,因为A和D不能连通。
 *      那怎么让A和D连通呢?有多种方案,比如:
 *      1. 从A站直接修地铁到D站,张三坐车方案:A -> D
 *      2. 从B站修地铁到D站,张三坐车方案:A -> B -> D
 *      3. 从B站修地铁到C站,张三坐车方案:A -> B -> C -> D
 *  2. 本程序的目标:
 *      输入一组数字对,如:`1 2`、`3 4`,判断两个数之间是否连通,如果不连通,则让他们连通
 *  3. 本程序原理
 *      假设有一个一维数组a,大小为10,a[0]到a[9]中存的值分别为0~9,即每个元素的值都不一样。
 *      程序认为,当a[i]和a[j]的值不一样时,i和j不连通,当两个值一样时,i和j连通。
 *      以a[1]到a[4]为例,程序初始值如下:
 *          a[1] a[2] a[3] a[4]
 *          1    2    3    4
 *      输入`1 2`后,a[1]和a[2]的值改成一样,表明1和2连通了:
 *          a[1] a[2] a[3] a[4]
 *          2    2    3    4
 *      输入`3 4`后(到这里,1和2连通,3和4连通):
 *          a[1] a[2] a[3] a[4]
 *          2    2    4    4
 *      输入`1 4`后(到这里1、2、3、4互相都连通了):
 *          a[1] a[2] a[3] a[4]
 *          4    4    4    4
 * </pre>
 *
 * @return
 */
main() {
  setbuf(stdout, NULL); // 将标准输出的缓存区清零,防止printf不及时打印
  int i, p, q, t, id[N];
  for (i = 0; i < N; i++) {
    id[i] = i;
  }
  printf("请输入一对数字(10以内),两个数字中间以空格分隔:\n");
  while (scanf("%d %d", &p, &q) == 2) {
    printf("处理之前的数组为:\t");
    for (i = 0; i < N; i++) {
      printf("%d ", id[i]);
    }
    if (id[p] == id[q]) {
      printf("\t连通:%d %d\n", p, q);
      continue;
    }
    // 【关键代码段】
    for (t = id[p], i = 0; i < N; i++) {
      if (id[i] == t) {
        id[i] = id[q];
      }
    }
    printf("\t不连通:%d %d\n", p, q);
    printf("处理之后的数组为:\t");
    for (i = 0; i < N; i++) {
      printf("%d ", id[i]);
    }
    printf("\n");
  }
}

六、过程示意图

在这里插入图片描述


七、补充说明

该算法是全书的第一个算法,当前的实现方式是不太推荐的,后续应该会有其他的方案,等学到了再写文章。


全文完

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值