深度优先搜索

流过昼夜 提交于 2019-11-29 07:21:32

深度优先搜索也称深度寻路 

规则:沿一个方向行走,走到了岔路口有选择一个方向进行前进 若碰到死胡同 退到上一个岔路口重新选择方向 走过的路不会再走 一次只能走一个点

1.准备地图(二维数组 用1表示障碍 不可通行 用0表示可以通行

 1 #define MAP_ROW 10 2 #define MAP_COL 10 

2.准备方向

 1 enum Path_Dir{p_up,p_down,p_left,p_right}; 

3.准备一个栈用来保存搜索中可以行走的路径点信息

 1 #pragma one
 2 template<typename T>
 3 class CMyStack
 4 {
 5     T *pBuff;
 6     size_t len;
 7     size_t maxSize;
 8 public:
 9     CMyStack();
10     ~CMyStack();
11     void clear();
12 public:
13     void push(T const& elem);
14     void pop();
15     T const& getTop() const{ return pBuff[len - 1]; }
16     bool empty() const{ return len == 0; }
17 };
18 
19 template<typename T>
20 void CMyStack<T>::pop()
21 {
22     --len;
23 }
24 
25 template<typename T>
26 void CMyStack<T>::push(T const& elem)
27 {
28     if (len>=maxSize)
29     {
30         maxSize = maxSize + ((maxSize >> 1) > 1 ? (maxSize >> 1) : 1);
31         T *tempBuff = new T[maxSize];
32         for (size_t i = 0; i < len; i++)
33             tempBuff[i] = pBuff[i];
34         if (pBuff != nullptr)
35             delete[] pBuff;
36         pBuff = tempBuff;
37     }
38     pBuff[len++] = elem;
39 }
40 
41 template<typename T>
42 void CMyStack<T>::clear()
43 {
44     if (pBuff!=nullptr)
45     {
46         delete[] pBuff;
47         pBuff = nullptr;
48         len = maxSize = 0;
49     }
50 }
51 
52 
53 template<typename T>
54 CMyStack<T>::~CMyStack()
55 {
56     clear();
57 }
58 
59 template<typename T>
60 CMyStack<T>::CMyStack()
61 {
62     pBuff = nullptr;
63     len = maxSize = 0;
64 }

4.准备一个结构用来保存每一个路径点再二维数组的行列值

 1 struct MyPoint 2 { 3 int row, col; 4 }; 

5.准备一个辅助数组(1.资源地图数组不能变 2.对资源地图要进行数组标记)

1 struct PathNode
2 {
3     int val;//保存原始资源的路径点信息
4     Path_Dir dir;//当前路径点的方向标记
5     bool isFind;//当前路径点是否被访问过
6 };

准备一个函数 用来判断参数坐标是否可以通行

1 bool IsMove(PathNode p[][MAP_COL],int row,int col)
2 {
3     if (row < 0 || row >= MAP_ROW || col < 0 || col >= MAP_COL)
4         return false;//如果越界,不需要进行位置的判断
5     if (p[row][col].val != 0 || p[row][col].isFind == true)
6         return false;//表示当前行列的元素要么是障碍,要么已经被访问过,不能通行
7     return true;
8 }

第六步设置访问结点

 1     PathNode pathArr[MAP_ROW][MAP_COL];
 2     for (int i = 0; i < MAP_ROW; ++i)
 3     {
 4         for (int j = 0; j < MAP_COL; ++j)
 5         {
 6             pathArr[i][j].val = mapArr[i][j];
 7             pathArr[i][j].isFind = false;//表示地图中的每一个节点都没有被访问过
 8             pathArr[i][j].dir = p_up;//表示给地图中的每一个节点都设定一个初始方向
 9         }
10     }

第七步设置起点和终点

 1 MyPoint beginPoint = { 1, 1 }; 2 MyPoint endPoint = { 8, 8 }; 

第八步准备一个容器 来保存可通行路径

CMyStack<MyPoint> ms;
    ms.push(beginPoint);//把起点压入到容器中,用来查找后续的结点

第九步准备一个辅助坐标点 帮助来判断下一个可通行位置

 1 MyPoint NearPoint = beginPoint;//辅助点先为起点,然后通过起点设定的方向来对周边路径进行搜索 

第十步开始寻路

 1 while (true)//无法确定循环次数
 2     {
 3         switch (pathArr[NearPoint.row][NearPoint.col].dir)//判断当前起点在辅助数组中设定的方向
 4         {
 5         case p_up:
 6             //if (pathArr[NearPoint.row - 1][NearPoint.col].val == 0 &&    //表示当前点的上一行位置是可通行的
 7             //    pathArr[NearPoint.row - 1][NearPoint.col].isFind == false)//表示当前点的上一行位置是没有访问的
 8             pathArr[NearPoint.row][NearPoint.col].dir = p_left;//当前路口的下一个方向标记出来
 9             if (IsMove(pathArr, NearPoint.row - 1, NearPoint.col))
10             {
11                 //表示当前坐标的上方向能通行
12                 pathArr[NearPoint.row][NearPoint.col].isFind = true;//当前点改为已访问
13                 MyPoint temp = { NearPoint.row - 1, NearPoint.col };
14                 ms.push(temp);//压入这个坐标
15                 NearPoint = temp;//把这个上方向可通行的点赋值给辅助点,进行下一次的搜索
16             }
17             break;
18         case p_left:
19             pathArr[NearPoint.row][NearPoint.col].dir = p_down;//当前路口的下一个方向标记出来
20             if (IsMove(pathArr, NearPoint.row, NearPoint.col - 1))
21             {
22                 //表示当前坐标的上方向能通行
23                 pathArr[NearPoint.row][NearPoint.col].isFind = true;//当前点改为已访问
24                 MyPoint temp = { NearPoint.row, NearPoint.col - 1 };
25                 ms.push(temp);//压入这个坐标
26                 NearPoint = temp;//把这个上方向可通行的点赋值给辅助点,进行下一次的搜索
27             }
28             break;
29         case p_down:
30             pathArr[NearPoint.row][NearPoint.col].dir = p_right;//当前路口的下一个方向标记出来
31             if (IsMove(pathArr, NearPoint.row + 1, NearPoint.col))
32             {
33                 //表示当前坐标的上方向能通行
34                 pathArr[NearPoint.row][NearPoint.col].isFind = true;//当前点改为已访问
35                 MyPoint temp = { NearPoint.row + 1, NearPoint.col };
36                 ms.push(temp);//压入这个坐标
37                 NearPoint = temp;//把这个上方向可通行的点赋值给辅助点,进行下一次的搜索
38             }
39             break;
40         case p_right://最后一个方向,表示前面三个方向已经搜索完成
41             if (IsMove(pathArr, NearPoint.row, NearPoint.col + 1))
42             {
43                 //表示当前坐标的上方向能通行
44                 pathArr[NearPoint.row][NearPoint.col].isFind = true;//当前点改为已访问
45                 MyPoint temp = { NearPoint.row, NearPoint.col + 1};
46                 ms.push(temp);//压入这个坐标
47                 NearPoint = temp;//把这个上方向可通行的点赋值给辅助点,进行下一次的搜索
48             }
49             else
50             {
51                 //表示当前路口所有方向都不通,要准备退栈
52                 MyPoint tempPoint = ms.getTop();//得到退栈之前的栈顶元素
53                 pathArr[tempPoint.row][tempPoint.col].isFind = true;//要退出栈的这个元素也是已经访问过了
54                 ms.pop();
55                 if (!ms.empty())//如果栈不为空
56                     NearPoint = ms.getTop();//得到新的栈顶元素
57             }
58             break;
59         }
60 
61         if (NearPoint.row ==  endPoint.row && NearPoint.col == endPoint.col)
62             break;//找到终点
63         if (ms.empty())
64             break;//没有终点
65     }
66 
67     while (!ms.empty())
68     {
69         MyPoint tempPoint = ms.getTop();
70         printf("row = %d, col = %d\n",tempPoint.row,tempPoint.col);
71         ms.pop();
72     }

总体代码

 1 #pragma one
 2 template<typename T>
 3 class CMyStack
 4 {
 5     T *pBuff;
 6     size_t len;
 7     size_t maxSize;
 8 public:
 9     CMyStack();
10     ~CMyStack();
11     void clear();
12 public:
13     void push(T const& elem);
14     void pop();
15     T const& getTop() const{ return pBuff[len - 1]; }
16     bool empty() const{ return len == 0; }
17 };
18 
19 template<typename T>
20 void CMyStack<T>::pop()
21 {
22     --len;
23 }
24 
25 template<typename T>
26 void CMyStack<T>::push(T const& elem)
27 {
28     if (len>=maxSize)
29     {
30         maxSize = maxSize + ((maxSize >> 1) > 1 ? (maxSize >> 1) : 1);
31         T *tempBuff = new T[maxSize];
32         for (size_t i = 0; i < len; i++)
33             tempBuff[i] = pBuff[i];
34         if (pBuff != nullptr)
35             delete[] pBuff;
36         pBuff = tempBuff;
37     }
38     pBuff[len++] = elem;
39 }
40 
41 template<typename T>
42 void CMyStack<T>::clear()
43 {
44     if (pBuff!=nullptr)
45     {
46         delete[] pBuff;
47         pBuff = nullptr;
48         len = maxSize = 0;
49     }
50 }
51 
52 
53 template<typename T>
54 CMyStack<T>::~CMyStack()
55 {
56     clear();
57 }
58 
59 template<typename T>
60 CMyStack<T>::CMyStack()
61 {
62     pBuff = nullptr;
63     len = maxSize = 0;
64 }
MyStack.h
  1 //深度优先搜索.cpp : 定义控制台应用程序的入口点。
  2 //
  3 
  4 #include "stdafx.h"
  5 #include "MyStack.h"
  6 
  7 //深度优先搜索
  8 
  9 //作业:1、在示例中方向顺序为上,左,下,右,如果更换这个方向顺序会有什么影响?
 10 //        2、深度寻路在有路的情况下,不一定能找到路,为什么?
 11 
 12 //规则:沿一个方向进行行走,到了岔路口又一次选择一个方向进行前进,如果碰到死胡同退回到上一个岔路口重新选择方向
 13 //        走过的路不会再走,一次走一个节点
 14 
 15 //1、准备地图 (二维数组,用1表示是障碍,不可通行,用0表示可以通行)
 16 #define MAP_ROW 10
 17 #define MAP_COL 10
 18 
 19 //2、准备方向
 20 enum Path_Dir{ p_up, p_down,p_left,p_right };
 21 
 22 //3、准备一个栈,用来保存搜索过程中可以行走的路径点信息(在规划中有后进的先出)
 23 
 24 //4、准备一个结构,用来保存每一个路径点在二维数组的行列值
 25 struct MyPoint
 26 {
 27     int row, col;
 28 };
 29 
 30 //5、准备一个辅助数组(1、资源地图数组不能变;2、对资源地图要进数据标记)
 31 struct PathNode
 32 {
 33     int val;//保存原始资源的路径点信息
 34     Path_Dir dir;//当前路径点的方向标记
 35     bool isFind;//当前路径点是否被访问过
 36 };
 37 
 38 //准备一个函数,用来判断参数的坐标是否可以通行
 39 bool IsMove(PathNode p[][MAP_COL],int row,int col)
 40 {
 41     if (row < 0 || row >= MAP_ROW || col < 0 || col >= MAP_COL)
 42         return false;//如果越界,不需要进行位置的判断
 43     if (p[row][col].val != 0 || p[row][col].isFind == true)
 44         return false;//表示当前行列的元素要么是障碍,要么已经被访问过,不能通行
 45     return true;
 46 }
 47 
 48 
 49 int _tmain(int argc, _TCHAR* argv[])
 50 {
 51     int mapArr[MAP_ROW][MAP_COL] = {
 52         { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 },
 53         { 1, 0, 0, 1, 1, 0, 0, 0, 1, 1 },
 54         { 1, 1, 0, 1, 1, 0, 1, 0, 1, 1 },
 55         { 1, 1, 0, 0, 0, 0, 1, 0, 1, 1 },
 56         { 1, 1, 0, 1, 1, 0, 1, 0, 1, 1 },
 57         { 1, 1, 0, 1, 1, 0, 1, 0, 1, 1 },
 58         { 1, 1, 0, 1, 1, 0, 1, 0, 1, 1 },
 59         { 1, 1, 0, 1, 1, 0, 1, 0, 1, 1 },
 60         { 1, 0, 0, 1, 0, 0, 1, 0, 0, 1 },
 61         { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }
 62     };
 63 
 64     //第6步
 65     PathNode pathArr[MAP_ROW][MAP_COL];
 66     for (int i = 0; i < MAP_ROW; ++i)
 67     {
 68         for (int j = 0; j < MAP_COL; ++j)
 69         {
 70             pathArr[i][j].val = mapArr[i][j];
 71             pathArr[i][j].isFind = false;//表示地图中的每一个节点都没有被访问过
 72             pathArr[i][j].dir = p_up;//表示给地图中的每一个节点都设定一个初始方向
 73         }
 74     }
 75 
 76     //第7步
 77     MyPoint beginPoint = { 1, 1 };
 78     MyPoint endPoint = { 8, 8 };
 79 
 80     //第8步:准备一个容器,用来保存可通行路径点
 81     CMyStack<MyPoint> ms;
 82     ms.push(beginPoint);//把起点压入到容器中,用来查找后续的结点
 83 
 84     //第9步:准备一个辅助坐标点,帮助来判断下一个可通行位置
 85     MyPoint NearPoint = beginPoint;//辅助点先为起点,然后通过起点设定的方向来对周边路径进行搜索
 86 
 87     //第10步:开始寻路
 88     while (true)//无法确定循环次数
 89     {
 90         switch (pathArr[NearPoint.row][NearPoint.col].dir)//判断当前起点在辅助数组中设定的方向
 91         {
 92         case p_up:
 93             //if (pathArr[NearPoint.row - 1][NearPoint.col].val == 0 &&    //表示当前点的上一行位置是可通行的
 94             //    pathArr[NearPoint.row - 1][NearPoint.col].isFind == false)//表示当前点的上一行位置是没有访问的
 95             pathArr[NearPoint.row][NearPoint.col].dir = p_left;//当前路口的下一个方向标记出来
 96             if (IsMove(pathArr, NearPoint.row - 1, NearPoint.col))
 97             {
 98                 //表示当前坐标的上方向能通行
 99                 pathArr[NearPoint.row][NearPoint.col].isFind = true;//当前点改为已访问
100                 MyPoint temp = { NearPoint.row - 1, NearPoint.col };
101                 ms.push(temp);//压入这个坐标
102                 NearPoint = temp;//把这个上方向可通行的点赋值给辅助点,进行下一次的搜索
103             }
104             break;
105         case p_left:
106             pathArr[NearPoint.row][NearPoint.col].dir = p_down;//当前路口的下一个方向标记出来
107             if (IsMove(pathArr, NearPoint.row, NearPoint.col - 1))
108             {
109                 //表示当前坐标的上方向能通行
110                 pathArr[NearPoint.row][NearPoint.col].isFind = true;//当前点改为已访问
111                 MyPoint temp = { NearPoint.row, NearPoint.col - 1 };
112                 ms.push(temp);//压入这个坐标
113                 NearPoint = temp;//把这个上方向可通行的点赋值给辅助点,进行下一次的搜索
114             }
115             break;
116         case p_down:
117             pathArr[NearPoint.row][NearPoint.col].dir = p_right;//当前路口的下一个方向标记出来
118             if (IsMove(pathArr, NearPoint.row + 1, NearPoint.col))
119             {
120                 //表示当前坐标的上方向能通行
121                 pathArr[NearPoint.row][NearPoint.col].isFind = true;//当前点改为已访问
122                 MyPoint temp = { NearPoint.row + 1, NearPoint.col };
123                 ms.push(temp);//压入这个坐标
124                 NearPoint = temp;//把这个上方向可通行的点赋值给辅助点,进行下一次的搜索
125             }
126             break;
127         case p_right://最后一个方向,表示前面三个方向已经搜索完成
128             if (IsMove(pathArr, NearPoint.row, NearPoint.col + 1))
129             {
130                 //表示当前坐标的上方向能通行
131                 pathArr[NearPoint.row][NearPoint.col].isFind = true;//当前点改为已访问
132                 MyPoint temp = { NearPoint.row, NearPoint.col + 1 };
133                 ms.push(temp);//压入这个坐标
134                 NearPoint = temp;//把这个上方向可通行的点赋值给辅助点,进行下一次的搜索
135             }
136             else
137             {
138                 //表示当前路口所有方向都不通,要准备退栈
139                 MyPoint tempPoint = ms.getTop();//得到退栈之前的栈顶元素
140                 pathArr[tempPoint.row][tempPoint.col].isFind = true;//要退出栈的这个元素也是已经访问过了
141                 ms.pop();
142                 if (!ms.empty())//如果栈不为空
143                     NearPoint = ms.getTop();//得到新的栈顶元素
144             }
145             break;
146         }
147 
148         if (NearPoint.row == endPoint.row && NearPoint.col == endPoint.col)
149             break;//找到终点
150         if (ms.empty())
151             break;//没有终点
152     }
153 
154     while (!ms.empty())
155     {
156         MyPoint tempPoint = ms.getTop();
157         printf("row = %d, col = %d\n", tempPoint.row, tempPoint.col);
158         ms.pop();
159     }
160     return 0;
161 }
深度优先搜索.cpp

 

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!