深度优先搜索也称深度寻路
规则:沿一个方向行走,走到了岔路口有选择一个方向进行前进 若碰到死胡同 退到上一个岔路口重新选择方向 走过的路不会再走 一次只能走一个点
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 }
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 }