• C/C++数据结构——列出连通集(深搜和广搜)


    活动地址:CSDN21天学习挑战赛
    学习的最大理由是想摆脱平庸,早一天就多一份人生的精彩;迟一天就多一天平庸的困扰。

    题目描述

    给定一个有N个顶点和E条边的无向图,请用DFS和BFS分别列出其所有的连通集。假设顶点从0到N−1编号。进行搜索时,假设我们总是从编号最小的顶点出发,按编号递增的顺序访问邻接点。

    输入格式:

    输入第1行给出2个整数N(0

    输出格式:

    按照"{ v1 v2…vk}"的格式,每行输出一个连通集。先输出DFS的结果,再输出BFS的结果。

    输入样例:

    8 6
    0 7
    0 1
    2 0
    4 1
    2 4
    3 5

    输出样例:

    { 0 1 4 2 7 }
    { 3 5 }
    { 6 }
    { 0 1 2 7 4 }
    { 3 5 }
    { 6 }

    解题代码

    #include
    #include
    //深搜
    void dfs(int map[][15],int f[],int n,int x){
        printf("%d ",x);
        for(int i=0;i<n;i++){
            map[i][x]=0;
        }
        for(int i=0;i<n;i++){
            if(map[x][i]&&!f[i]){
                map[x][i]=0;
                map[i][x]=0;
                f[i]=1;
                dfs(map,f,n,i);
            }
        }
    }
    //广搜
    void bfs(int map[][15],int f[],int n,int x){
        for(int i=0;i<n;i++){
            map[i][x]=0;
        }
        for(int i=0;i<n;i++){
            if(map[x][i]&&!f[i]){
                printf("%d ",i);
                f[i]=1;
            }
        }
        for(int i=0;i<n;i++){
            if(map[x][i]){
                map[x][i]=0;
                map[i][x]=0;
                bfs(map,f,n,i);
            }
        }
        
    }
    void init(int map[][15],int temp[][15],int n){
        for(int i=0;i<n;i++){
            for(int j=0;j<n;j++){
                temp[i][j]=map[i][j];
            }
        }
    }
    int main()
    {
        int n,e;
        int v,u;
        int map[15][15],temp[15][15];
        int flag[15];
        while(scanf("%d%d",&n,&e)!=EOF)
        {
            memset(map,0,sizeof(map));
            for(int i=1;i<=e;i++){
                scanf("%d%d",&v,&u);
                map[v][u]=1;
                map[u][v]=1;
            }
            memset(flag,0,sizeof(flag));
            init(map,temp,n);
            for(int i=0;i<n;i++){
                if(!flag[i]){
                    flag[i]=1;
                    printf("{ ");
                    dfs(temp,flag,n,i);
                    printf("}\n");
                }
            }
            init(map,temp,n);
            memset(flag,0,sizeof(flag));
            for(int i=0;i<n;i++){
                if(!flag[i]){
                    flag[i]=1;
                    printf("{ %d ",i);
                    bfs(temp,flag,n,i);
                    printf("}\n");
                }
            }
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80

    解题思路

    就是深搜广搜,emmm,我也就照着我自己的思路写的,如果有更简单的更简洁的代码可以一起分享一下。
    深搜就是路经该结点的路劲有多条,先走完一条路径再回来走另一条。广搜就是一个结点下有多个结点可以走,那就先走完输出所有结点,然后再走这些节点的下一个结点,就相当于二叉树的层次遍历,上层结点走完再走下层节点。
    在这里插入图片描述
    样例我们可以得出上图这样一张图,我是用邻接表存的,反正画出来就是这么一个无向图。
    深搜DFS的步骤的如下:
    从0开始,我们题目要求从编号小的开始,集合{0}。
    在这里插入图片描述
    然后呢这时,0有两个连接的结点,1和2,从小的开始那就是先走1.集合{0,1}
    在这里插入图片描述
    这时候1有结点4连接,深度优先嘛,先走到底,那么接下来走4.得到集合{0,1,4}
    在这里插入图片描述
    然后4后还有一个相邻结点2,那么走2,得到集合{0,1,4,2}
    在这里插入图片描述
    此时这条路径已经走不下去了,没有可以走的地方了,然后就网上退,0这里还有路可以走7,得到集合{0,1,4,2,7}
    在这里插入图片描述
    这时候这一条路径完全走完了,走不了了,那就走下一个结点小的没走过的路径,那就是3开始,接下来就不赘述了。

    广搜步骤介绍
    依旧是从结点编号小的开始,得到集合{0}
    在这里插入图片描述
    广搜啊,所以要找当前节点相邻的所有结点,走完这些结点才可以继续。那么接下来就找相邻结点,那就是1,2,7,分别走过。小的优先,得到集合{0,1,2,7}
    在这里插入图片描述
    然后从刚才走过的结点开始往下找相邻的结点,把他们下一层结点都遍历了。遍历结点1的下一层,得到集合{0,1,2,7,4}
    在这里插入图片描述
    此时这条路径已经没有结点可以遍历了,接着便利其他未走过的路径,就不赘述了。

    我理解的就是这样的,如果有问题可以及时指出,共同探讨。
    我不理解但是,为什么说我的文章质量差来着。

    在这里插入图片描述

    一般来说,广搜常用于找单一的最短路线,或者是规模小的路径搜索,它的特点是"搜到就是最优解", 而深搜用于找多个解或者是"步数已知(好比3步就必需达到前提)"的标题,它的空间效率高,然则找到的不必定是最优解,必需记实并完成全数搜索,故一般情况下,深搜需要很是高效的剪枝(优化).

    像搜索最短路径这些的很显著若是用广搜,因为广搜的特征就是一层一层往下搜的,保证当前搜到的都是最优解,当然,最短路径只是一方面的操作,像什么起码状态转换也是可以操作的。
    深搜就是优先搜索一棵子树,然后是另一棵,它和广搜对比,有着内存需要相对较少的所长,八皇后标题就是典范楷模的操作,这类标题很显著是不能用广搜往解决的。或者像图论里面的找圈的算法,数的前序中序后序遍历等,都是深搜

    深搜和广搜的分歧之处是在于搜索次序的分歧。

    深搜的实现近似于栈,每次选择栈顶元素往扩年夜,

    广搜则是操作了队列,先被扩年夜的的节点优先拿往扩年夜。

    搜索树的形态:深搜层数良多,广搜则是很宽。

    深搜合适找出所有方案,广搜则用来找出最佳方案

    深搜和广搜的分歧:

    深搜并不能保证第一次碰着方针点就是最短路径,是以要搜索所有可能的路径,是以要回溯,标识表记标帜做了之后还要打消失踪,是以统一个点可能被访谒良多良多次。而广搜因为它的由近及远的结点扩年夜次序,结点老是以最短路径被访谒。一个结点假如第二次被访谒,第二次的路径确定不会比第一次的短,是以就没有需要再从这个结点向周围扩年夜――第一次访谒这个结点的时辰已经扩年夜过了,第二次再扩年夜只会获得更差的解。是以做过的标识表记标帜不必往失踪。是以统一个点至多只可能被访谒一次。每访谒一个结点,与它相连的边就被搜检一次。是以最坏情况下,所有边都被搜检一次,是以时刻复杂度为O(E)。

  • 相关阅读:
    消息中间件之ActiveMQ的基本使用
    多线程轮流打印
    学习用docker构建自己的镜像
    【W3Cschool之强化Python能力】
    腾讯mini项目-【指标监控服务重构】2023-07-26
    Docker容器搭建本地私有仓库
    MapRecuce框架原理
    Maven配置MAVEN_OPTS
    基于LVM通过添加硬盘实现分区扩容的方法介绍
    高电压放大器与高电流放大器该如何选择使用
  • 原文地址:https://blog.csdn.net/weixin_44546342/article/details/126136545