一、概念
深度优先搜索(Depth First Search)主要是用来遍历图存储结构的一种算法,它既使用于无向图,也适用于有向图。
图的遍历主要是逐个访问图中的每一个顶点,并且还要确保,图的所有顶点都只被访问一次。
二、具体步骤
深度优先搜索算法的原则主要就是从图中的某个顶点出发,不停的寻找相邻的、尚未访问的顶点:
1. 如果找到多个,则任选一个顶点,然后继续从该顶点出发。
2. 如果一个都没有找到,则回退之前访问过的顶点,看看是否存在漏掉的顶点。
3. 只到从V顶点出发,回退到V顶点。再向上面一样重复查找是否存在未访问过的顶点,不存在的话则算法结束。
通常情况下,深度优先搜索算法访问图中顶点的顺序是不唯一的,即顶点的访问序列可能有很多种(≥1)。
三、用深度优先搜索解迷宫案例
其实通过具体步骤的分析可以看出,在深度优先搜索的时候,可以用一个栈来维护当前结点。
首先给定一个二维数组来表示一个迷宫,其中1表示墙壁,0表示可以走的路,规定只能横着走和竖着走,不能斜着走,要求通过写一个程序,找出从左上角到右下角中的一条路线。
int maze[5][5] = {
0,1,0,0,0,
0,1,0,1,0,
0,0,0,0,0,
0,1,1,1,0,
0,0,0,1,0,
};
代码实现:
/*深度优先搜索遍历算法解决迷宫问题*/
#include<stdio.h>
#define MAX_ROW 5
#define MAX_COL 5
/*
堆栈中的元素是结构体类型
主要用来表示迷宫中的一个点x和y的坐标
*/
struct point{int row,col;}stack[512];
/*记录栈中元素的个数*/
int top = 0;
/*入栈操作*/
void push(struct point p)
{
stack[top++] = p;
}
/*取栈顶元素*/
struct point pop(void)
{
return stack[--top];
}
/*判断栈是否为空*/
int is_empty(void)
{
return top == 0;
}
/*
迷宫:走过的路通过2标识,防止重复走。
最后找到终点时就根据predecessor数组保存的路线打印
*/
int maze[MAX_ROW][MAX_COL] =
{
0,1,0,0,0,
0,1,0,1,0,
0,0,0,0,0,
0,1,1,1,0,
0,0,0,1,0,
};
/*打印*/
void print_maze(void)
{
int i,j;
for(i=0; i<MAX_ROW; i++){
for(j=0; j<MAX_COL; j++){
printf("%d ",maze[i][j]);
}
putchar('\n');
}
printf("************\n");
}
/*
记录前趋点,表示从哪走到当前点
predecessor[4][4]是坐标为(3,4)的点,就表示从(3,4)->(4,4)
*/
struct point predecessor[MAX_ROW][MAX_COL]={
{
{-1,-1}, {-1,-1}, {-1,-1}, {-1,-1}, {-1,-1}},
{
{-1,-1}, {-1,-1}, {-1,-1}, {-1,-1}, {-1,-1}},
{
{-1,-1}, {-1,-1}, {-1,-1}, {-1,-1}, {-1,-1}},
{
{-1,-1}, {-1,-1}, {-1,-1}, {-1,-1}, {-1,-1}},
{
{-1,-1}, {-1,-1}, {-1,-1}, {-1,-1}, {-1,-1}},
};
/*
记录顶点移动时候的信息
*/
void visit(int row,int col,struct point pre)
{
struct point visit_point = {row,col};//保存当前顶点的信息
maze[row][col] = 2;//标记访问过的顶点
predecessor[row][col] = pre;//保存之前顶点信息
push(visit_point);//压栈
}
int main(void)
{
/*初始化起始位置*/
struct point p = {0,0};
maze[p.row][p.col] = 2;
push(p);
/*栈非空*/
while(!is_empty()){
/*从栈顶弹出一个点p*/
p=pop();
/*如果这个顶点是终点*/
if(p.row == MAX_ROW-1 && p.col == MAX_COL-1)
break;
/*向右移动*/
if(p.col+1 < MAX_COL && maze[p.row][p.col+1]==0)
visit(p.row,p.col+1,p);
/*向下移动*/
if(p.row+1 < MAX_ROW && maze[p.row+1][p.col]==0)
visit(p.row+1,p.col,p);
/*向左移动*/
if(p.col-1 >= 0 && maze[p.row][p.col-1]==0)
visit(p.row,p.col-1,p);
/*向上移动*/
if(p.row-1 >= 0 && maze[p.row-1][p.col]==0)
visit(p.row-1,p.col,p);
}
if(p.row == MAX_ROW-1 && p.col == MAX_COL-1){
printf("(%d,%d)\n",p.row,p.col);
while(predecessor[p.row][p.col].row != -1){
p = predecessor[p.row][p.col];
printf("(%d,%d)\n", p.row, p.col);
}
}else{
printf("No path!\n");
}
return 0;
}
代码结果:
代码分析流程:
在深度优先搜索的过程中,借助了栈的方法达到回溯的要求。并通过配合标记2防止重复路线的访问。最后通过遍历predecessor来找出最后访问出来的路线。