提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档
前言—图/树
要学习深/广度 优先算法,就得先了解什么是图,以及树。
看了《啊哈!算法》以及搜索一些资料之后,初步有了自己非常不准确的 理解:
图可以简单的表达为点和线的一系列图形,而树就是整理后的一种有一定固定结构的图。
一、深度优先搜索(Deep Search First)
搜索,自己认为是对一堆有某种逻辑关系的数据进行搜索,且要求对每一个元素全部搜索到.虽然每一个元素都要“关注”到(所以也有人叫 深度优先遍历 ),但是用怎样的顺序走呢?
毕竟,很多情况下,我们大概率会在“半路”遇到所需要的结果,完全不需要完全遍历,那将会需要大量的时间复杂度。
所以,将搜索分为两种搜素的优先顺序—深度优先和广度优先。
由上图的树/图看,可以很形象的顾名思义—深度优先就是先“挖到底”,再回到浅一层,再往下挖。
二、《啊哈!算法》题目及其代码分析
题目:输入一个数字,然后写出对应的全排列。
例如:输入3
输出
1 2 3
1 3 2
2 1 3
2 3 1
3 1 2
3 2 1
代码如下:
#include <stdio.h>
#include <string.h>
int a[10],book[10],n;
void dfs(int step);
int main(){
scanf("%d",&n);
dfs(1);
getchar();
return 0;
}
void dfs(int step)
{
int i;
if(step==n+1)
{//边界判断 ,这一个if就是一个出口,当进行到最后的时候才会用得上这个判断
for(int i=1;i<=n;i++)
printf("%d ",a[i]);
printf("\n");
return ;//返回出口
}
for(int i=1;i<=n;i++)//一个个地尝试
{
if(book[i]==0)//需要判断手中牌是否还在
{
a[step]=i;
book[i]=1;//标记为已经有了
dfs(step+1);
book[i]=0;//回溯的出口,要及时把牌收回来
}
}
return;//回溯
}
总结
深度优先搜索的核心知识之一就是—递归,但又不仅仅在于递归。
如书中所说,DSF关键在于“当下如何做”,而下一步如何做,其实就是重复“当前做什么”。
给出的大致模板就是
void dfs()
{
判断边界
例如上题中的if判断语句,达到某种触发条件就需要做一次“清理”
如printf一些内容 ,然后出口是return
尝试每一种可能
for(){
进入下一步 dfs()
有时候从上一层出来后 也需要一些清理工作。
}
return
}