【算法】DFS深度优先搜索:递归实现

一.DFS

    1.介绍

       DFS(Depth-First-Search)不同于BFS广度优先搜索,它更加侧重于对树/图进行深度搜索,在搜索时,从根节点开始一直往下到没有节点可以搜索为止,在搜索过程中可将路径进行保存。实现DFS深度优先搜索可借用“栈”来实现,递归或者非递归的方法均可,在解决迷宫问题时,在寻找迷宫出口问题上使用DFS是个合适的选择。

    2.图解

                       【算法】DFS深度优先搜索:递归实现_第1张图片

       如图上所示,灰色部分为墙壁,如果想从“起点”位置到达“终点”,使用DFS时,会将所有“可能”的路径都走一遍,直到无路可走仍未发现终点时,将退回至最近一次分叉路口从另一条路继续往下寻找,直到找到终点位置。

                       【算法】DFS深度优先搜索:递归实现_第2张图片

       第一次向左走至尽头,没有发现终点,则回到“起点”处,开始往下寻找。

                        【算法】DFS深度优先搜索:递归实现_第3张图片

       当走到“黑色箭头”标记处时,发现该节点为“分叉点”,故DFS记录这个位置,选择一条路径开始往下寻找。

                        【算法】DFS深度优先搜索:递归实现_第4张图片

      往下走到尽头后发现找不到尽头,故退回到“分叉点”,开始往右边寻找。

                       【算法】DFS深度优先搜索:递归实现_第5张图片

      向右走又出现了分叉点,故DFS记录这个位置,选择一条路径开始往上寻找。

                        【算法】DFS深度优先搜索:递归实现_第6张图片

      走到尽头后发现没有到终点所以回到最近一次“分叉点”进行往下寻找。

                        【算法】DFS深度优先搜索:递归实现_第7张图片

      找到终点,结束。

二.递归寻找迷宫出口

    1.问题描述

      DFS最经典的问题之一,寻找迷宫中起点到终点的路径:{{0, 0, 1, 0, 1}, 
                                                                                                 {0, 1, 1, 1, 0},
                                                                                                 {0, 0, 0, 0, 0},
                                                                                                 {0, 1, 1, 1, 0},
                                                                                                 {0, 0, 0, 1, 0}};

     2.代码源码

       2.1.记录二维网格坐标位置、是否为墙壁、是否走过等状态

struct Node
{
	int _x;
	int _y;
	int _value;
	bool _IsWall;
	bool _IsWalked;
};

vector> Push_Node(std::vector>& push_into)
{
	std::vector> push;
	int state;

	for (int i = 0; i < push_into.size(); i++)
	{
		std::vector into;
		for (int j = 0; j < push_into[i].size(); j++)
		{
			if (push_into[i][j] == 1)
				state = true;
			else
				state = false;

			Node node{ i,j,push_into[i][j],state,false };
			into.push_back(node);
		}
		push.push_back(into);
	}

	return push;
}

       2.2.寻找指定节点的相邻节点,详细代码可参考我之前写过的文章:【C/C++】获取二维数组相邻八个/四个方向的数据

std::vector Find_Beighbors(int x, int y, std::vector>& vec)
{
	int max_x = (vec.size() - 1);
	int max_y = ((vec[x].size()) - 1);
	std::vector list; //扩列存储相邻元素

	for (int dx = (x > 0 ? -1 : 0); dx <= (x < max_x ? 1 : 0); ++dx)
	{
		for (int dy = (y > 0 ? -1 : 0); dy <= (y < max_y ? 1 : 0); ++dy)
		{
			if ((dx == 0 || dy == 0) && (dx + dy != 0))
			{
				list.push_back(vec[x + dx][y + dy]);
			}
		}
	}
	return list;
}

        2.3.核心部分,使用递归进行DFS搜索,递归使用的是系统的栈,简称隐式栈

bool DFS(Node root, Node target, vector>& push_into)  //递归调用,隐形栈
{
	if (root._x == target._x && root._y == target._y)
		return true;

	push_into[root._x][root._y]._IsWalked = true;
	vector Beighbors = Find_Beighbors(root._x, root._y, push_into);

	for (int i = 0; i < Beighbors.size(); i++)
	{
		if (!push_into[Beighbors[i]._x][Beighbors[i]._y]._IsWall)
		{
			if (!push_into[Beighbors[i]._x][Beighbors[i]._y]._IsWalked)
			{
				push_into[Beighbors[i]._x][Beighbors[i]._y]._IsWalked = true;
				if (DFS(push_into[Beighbors[i]._x][Beighbors[i]._y], target, push_into))
				{
					push_into[Beighbors[i]._x][Beighbors[i]._y]._value = 3; //标记路径
					printf("(%d,%d)\n",push_into[Beighbors[i]._x][Beighbors[i]._y]._x, push_into[Beighbors[i]._x][Beighbors[i]._y]._y);
					return true;
				}
			}
		}
	}
	return false;
}

      3.实际使用情况

            起始节点坐标:(0,0),目标节点坐标:(4,4),输出为:

             【算法】DFS深度优先搜索:递归实现_第8张图片

           起始节点坐标:(0,0),目标节点坐标:(4,2),输出为:

             【算法】DFS深度优先搜索:递归实现_第9张图片

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