深度优先搜索之全排列问题(C语言版)

本文的一些参考:

DFS (深度优先搜索) 算法详解 + 模板 + 例题,这一篇就够了_dfs算法-CSDN博客

首先把深度优先搜索算法的基本概论摆出来

深度优先搜索算法(Depth First Search,简称DFS):

一种用于遍历或搜索树或图的算法。 沿着树的深度遍历树的节点,尽可能深的搜索树的分支。当节点v的所在边都己被探寻过或者在搜寻时结点不满足条件,搜索将回溯到发现节点v的那条边的起始节点。整个进程反复进行直到所有节点都被访问为止。属于盲目搜索,最糟糕的情况算法时间复杂度为O(!n)。

说白了就是沿着一条路走到底,然后发现没路了就开始回头走(回溯),走到上一个路口再按其他的没走过的路再走到底,再回头.......直到把这个路口的路走完了再回到这个路口的上一个路口,如此反复直到把路都走完!!!!!!

一、基本思想

为了求得问题的解,先选择某一种可能情况向前探索;

在探索过程中,一旦发现原来的选择是错误的,就退回一步重新选择,继续向前探索;

如此反复进行,直至得到解或证明无解。

二、操作步骤示例:

初始原点为v0,使用深度优先搜索,首先访问 v0 -> v1 -> v2 -> v5,到 v5 后面没有结点,则回溯到 v1 ,即最近的且连接有没访问结点的结点v1;

此次从 v1 出发,访问 v1 -> v4 -> v6 -> v3,此时与v3相连的两个结点 v0 与 v6 都已经访问过,回溯到 v6 (v6 具有没访问过的结点);

此次从 v6 出发,访问 v6 -> v7,到 v7 后面没有结点,回溯;

一直回溯到源点 v0 ,没有没访问过的结点,程序结束。

注:下面图中箭头为回溯方向

三、代码模板
cpp 复制代码
#include<stdio.h>
int n; //从n个数据中取
int a[1001]; //用来存储被读取数据
int book[1001]; //用来标记是否被访问(读取)
int s=0; //记录符合条件的次数

void dfs(int sept){
    if(sept>n){ //已经把n个数据都读完了,可以进行相应的一些打印之类的操作
        for(int i=1;i<=n;i++){
            printf("%d ",a[i]);
        }
        printf("\n");
    }
    else{ //要是没读完就继续读数据
        for(int i=1;i<=n;i++){ //一个个遍历找还没读取的
            if(book[i]==0){ //0代表还没有被标记即未取出
                book[i]=1; //把这个数据标记为1即已经取出
                a[sept]=i; //把这个数据存进a里
                dfs(sept+1); //前sept个元素就已经取出来了现在去取后面的元素,直到全部取出为止
                book[i]=0; //取完了就把标记释放方便下次取出即回溯
            }
        }
    }
}

int main()
{
    scanf("%d",&n);
    dfs(1);
    return 0;
}

把概念和算法的底层逻辑搞明白之后就开始实战

全排列

按照字典序输出自然数 1 到 n 所有不重复的排列,即 n 的全排列,要求所产生的任一数字序列中不允许出现重复的数字。

输入格式:

一个整数 n(n<=5)。

输出格式:

由 1~n 组成的所有不重复的数字序列,每行一个序列。

输入样例:

复制代码
3
输出样例:
复制代码
1 2 3 
1 3 2 
2 1 3 
2 3 1 
3 1 2 
3 2 1 
解题思路:

这是一个很经典的多叉数,就按照上面的这种顺序来进行深度优先搜索就行了

还是没懂可以看看这篇

C语言全排列算法(最详细讲解)-CSDN博客

代码实现:
cpp 复制代码
#include<stdio.h>
//深度优先搜索
int n;//对n个数进行全排列
int book[1001];//标记
int a[10];//存储数据

void dfs(int step){//step为现在排到第几个数了
    if(step>n){
        for(int i=1;i<=n;i++){
            if(i<n){
                printf("%d ",a[i]);
            }
            else{
                printf("%d\n",a[i]);
            }
        }
    }
    else{
        for(int i=1;i<=n;i++){
            if(book[i]==0){
                a[step]=i; //拿下该值
                book[i]=1; //标记
                dfs(step+1); //往下遍历
                book[i]=0; //回溯
            }
        }
    }
}

int main()
{
    scanf("%d",&n);
    dfs(1); //启动!
    return 0;
}
相关推荐
HaiLang_IT11 小时前
【目标检测】基于卷积神经网络的轨道部件(扣件、轨枕、钢轨)缺陷检测算法研究
算法·目标检测·cnn
草莓熊Lotso11 小时前
《算法闯关指南:优选算法--前缀和》--31.连续数组,32.矩阵区域和
c++·线性代数·算法·矩阵
csuzhucong11 小时前
斜转魔方、斜转扭曲魔方
前端·c++·算法
喜欢踢足球的老罗11 小时前
Qoder AI IDE深度体验:用Repo Wiki与AskModel重塑开源库学习范式
人工智能·学习·qoder
C语言不精12 小时前
c语言-优雅的多级菜单设计与实现
c语言·开发语言·算法
AI科技星12 小时前
张祥前统一场论:引力场与磁矢势的关联,反引力场生成及拉格朗日点解析(网友问题解答)
开发语言·数据结构·经验分享·线性代数·算法
C雨后彩虹12 小时前
最少交换次数
java·数据结构·算法·华为·面试
可可苏饼干12 小时前
NoSQL 与 Redis
数据库·redis·笔记·学习·nosql
重生之我在番茄自学网安拯救世界12 小时前
网络安全中级阶段学习笔记(一):DVWA靶场安装配置教程与网络空间搜索语法
笔记·学习·网络安全·靶场·dvwa·fofa·google hack
-森屿安年-12 小时前
二叉平衡树的实现
开发语言·数据结构·c++