数据结构_dfs深度优先算法入门(C语言)

数据结构_dfs深度优先算法入门(C语言)

文章目录

  • 数据结构_dfs深度优先算法入门(C语言)
    • 0.闲话
    • 1.个人理解
    • 2.全排列问题(1到n的排列组合)
    • 2.八皇后问题求解
    • 3.二维迷宫
      • (1)只输走出迷宫解的个数
      • (2)输出解的个数和路径

0.闲话

​ 才学习数据结构的dfs,做一下笔记记录一下,加深理解-.-

​ 我这里就简单讲一下我的理解和一下例子

​ 推荐学习资源(B站视频,原理和实例):

洛谷 普及组( CSP - J )试炼场 - 深度优先搜索 (DFS)

​ 编译环境:vc++6.0

1.个人理解

dfs,名叫深度优先搜索,就是从一个节点一直往深处搜索,直到走到尽头,再往回走,走下一个节点,再次深搜……就相当于来回遍历,一个人走迷宫。

所以,dfs是运用递归的方法,基于回溯的思想。而回溯就是基于栈结构

栈结构的话,直接用数组来实现就可以了。

重点:C代码一定要从main函数开始看。

2.全排列问题(1到n的排列组合)

​ 全排列问题的一个重点:比如走迷宫一样,最开始有个起始点,下一步有多个选择。当我们要深搜时,如果没有一个固定的起始点,我们要假想构造一个0起始点,从0起始点开始往下走选择。以此来构造一个有规律可递归的函数。

数据结构_dfs深度优先算法入门(C语言)_第1张图片

#include
#define N 20
int n;//将其设置为全局变量
int visit[N]={0};//0代表未访问,1代表已访问。
int a[N] = {0};//记录全排列的方式。

//输出函数
void printF()
{
	int i ;
	for(i=1 ; i<=n ; i++)
		printf("%5d",a[i]);
	printf("\n");
}

void dfs(int x)//x代表递归的层数
{
	int i;
	if(x>n)
		printF();//输出一种结果
	
	for(i=1 ; i<=n ; i++)//递归时,每层都有循环
	{
		if(!visit[i])//i这个数是否排过序。
		{
			visit[i] = 1;//代表排过序
			a[x] = i;//记录i
			
			dfs(x+1);//进入下一层递归
			
			//回溯,归零。
			visit[i] = 0;
			a[x] = 0;//这一步可以不写
		}
	}	
}

int main()
{

	printf("Please input n:");
	scanf("%d",&n);

	dfs(1);


	return 0;
}

2.八皇后问题求解

简述规则就是,每行每列每个斜对角线只能站一个皇后,斜对角线包括左上到右下,和左下到右上,两种。

数据结构_dfs深度优先算法入门(C语言)_第2张图片

数据结构_dfs深度优先算法入门(C语言)_第3张图片

其实也是在全排列的基础上,加上八皇后特有的条件,进行递归。

#include
#define N 20
	
int n;

int u[2*N] = {0};//右上到左下,防止皇后在同一斜对角线。
int v[2*N] = {0};//左上到右下,1代表斜对角线有皇后,0代表没有。

int list[N] = {0};//记录同一列
int a[N] = {0};//记录皇后的位置
int sum = 0;//记录解法

void printF()//将得到的结果输出
{
	int i;	
	for( i=1 ; i<=n ; i++)
		printf("%2d",a[i]);
	putchar('\n');
}

void dfs(int x)
{	
	int i,j;

	if( x>n )
	{	
		sum++;
		printF();//将一种结果输出
		return ;
	}
	for(i=1 ; i<=n ; i++)//代表每行
	{
		if(list[i]==0 && u[x+i]==0 && v[x-i+n]==0)
		{
			//置一,代表这些位置不能再放皇后
			list[i] = 1;
			u[x+i] = 1;
			v[x-i+n] = 1;//防止相减后是负数,同一所有加个n。
			
			a[x] = i;//记录这个位置,x代表行,i代表列。

			dfs(x+1);

			//回溯,相当于栈结构
			list[i] = 0;
			u[x+i] = 0;
			v[x-i+N] = 0;
			a[x] = 0;
		}		
	}
}	
	
int main()
{	
	printf("Please input n: ");//n皇后
	scanf("%d",&n);
	dfs(1);
	printf("There are %d sulutions!\n",sum);
	
}

3.二维迷宫

​ 输入:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-E36lukTz-1585555095740)(E:/Typora/image/1585458835224.png)]

​ 输入规则:

  1. 第一行输入行n、列m、障碍个数t
  2. 第二行分别输入起始坐标sx、sy和终点坐标fx、fy
  3. 第三行即后面依次每行输入一个障碍坐标,(根据输入的障碍个数)。

数据结构_dfs深度优先算法入门(C语言)_第4张图片

(1)只输走出迷宫解的个数

//三、二维迷宫求解:求解的个数。
#include
#define N 20

int n,m,t;//行、列、障碍个数
int sx,sy,fx,fy;//起始位置,终点位置。

int map[N][N] = {0};//标记障碍。
int visit[N][N] = {0};//标记是否走过。

int xx[] = {1,0,-1,0};
int yy[] = {0,1,0,-1};

int sum = 0; //记录总数。

void dfs(int x,int y)
{
	int i;
	int dx,dy;//记录下一步的位置。
	if(x==fx && y==fy)
		sum++;


	for(i=0 ; i<4 ; i++)
	{
		dx = xx[i] + x;
		dy = yy[i] + y;
		
		if(dx>=1 && dx<=n && dy>=1 && dy<=m && !map[dx][dy] && !visit[dx][dy])
		{
			visit[dx][dy] = 1;
			
			dfs(dx,dy);
			
			visit[dx][dy] = 0;
		}
	}
}


int main()
{
	int x,y;//记录障碍位置。
	printf("Please input : \n");
	scanf("%d%d%d",&n,&m,&t);//输入行、列、障碍个数
	scanf("%d%d%d%d",&sx,&sy,&fx,&fy);//数去起始坐标和终点坐标
	while(t--)
	{
		scanf("%d%d",&x,&y);
		map[x][y] = 1;//标记障碍坐标
	}
	
	visit[sx][sy] = 1;
	
	dfs(sx,sy);//从起点位置开始递归。

	printf("There are %d solution!\n",sum);
	return 0;
}

(2)输出解的个数和路径

数据结构_dfs深度优先算法入门(C语言)_第5张图片

#include
#define N 20

int n,m,t;//n为行,m为列,t为障碍数。
int sx,sy;//起点坐标。
int fx,fy;//终点坐标。
int map[N][N] = {0};//地图,标记障碍。
int visit[N][N] = {0};//记录是否走过。

char a[N*N] = {0};//记录上下左右。
int sum = 0;//记录路径总数。

//输出函数,每次输出路径和增加解的个数
void printF(int k)
{
	int i;
	for(i=1 ; i<=k ; i++)
		printf("%c",a[i]);

	printf("\n");
	sum++;
}
//x、y代表此时的位置,k代表走到第几步,方便记录路径。
void dfs(int x, int y, int k)
{
	int i;
	int dx,dy;//记录当前位置。

	if(x==fx && y==fy)//走出迷宫输出输出路径
	{
		printF( k-1 );
		return;
	}
	for(i=0 ; i<4 ; i++)//只有四种走法,上下左右。
	{	
		//如果不满足则for循环回到这一层函数开始的坐标位置
		dx = x;//这也是回溯,
		dy = y;//这也是回溯
		
		switch (i)
		{
			case 0:
				dx++;
				a[k] = 's';//上
				break;
			case 1:
				dy++;
				a[k] = 'y';//右
				break;
			case 2:
				dx--;
				a[k] = 'x';//下
				break;
			case 3:
				dy--;
				a[k] = 'z';//左
				break;					
		}
		if(dx>=1 && dx<=n && dy>=1 && dy<=m && !visit[dx][dy] && !map[dx][dy])//所有条件
		{
			visit[dx][dy] = 1;//标记走过

			dfs(dx,dy,k+1);//进入下一层递归

			visit[dx][dy] = 0;//回溯
		}
	}
}


//所有的x都代表行数,y代表列数。
int main()
{
	int i;
	int x,y;//记录障碍点。
	printf("Please input : \n");
	scanf("%d%d%d",&n,&m,&t);//输入行、列、障碍个数
	scanf("%d%d%d%d",&sx,&sy,&fx,&fy);//数去起始坐标和终点坐标
	while(t--)//循环输入障碍坐标
	{
		scanf("%d%d",&x,&y);
		map[x][y] = 1;//标记障碍坐标
	}
	
	visit[sx][sy] = 1;//代表第一步已走。
	dfs(sx,sy,1);//从起点位置开始递归。1代表第一步
	
	printf("There are %d solutions!\n",sum);

	return 0;
}


欢迎大家留言交流0.0

你可能感兴趣的:(C语言,数据结构_算法)