圖論
使用棧容器
起始方向不一樣會影響尋路速度和路徑
有多條路徑的情況下無法找到最短路徑
用於知道終點的方位的場景
MyStack.h
#pragma once
template<typename T>
class CMyStack
{
T *pBuff;
size_t len;
size_t maxSize;
public:
CMyStack();
~CMyStack();
void clear();
public:
void push(T const& elem);
void pop();
T const& getTop() const { return pBuff[len - 1]; }
bool empty() const { return len == 0; }
};
template<typename T>
void CMyStack<T>::pop()
{
--len;
}
template<typename T>
void CMyStack<T>::push(T const& elem)
{
if (len >= maxSize)
{
maxSize = maxSize + ((maxSize >> 1) > 1 ? (maxSize >> 1) : 1);
T *tempBuff = new T[maxSize];
for (size_t i = 0; i < len; ++i)
tempBuff[i] = pBuff[i];
if (pBuff != nullptr)
delete[] pBuff;
pBuff = tempBuff;
}
pBuff[len++] = elem;
}
template<typename T>
void CMyStack<T>::clear()
{
if (pBuff != nullptr)
delete[] pBuff;
pBuff = nullptr;
len = maxSize = 0;
}
template<typename T>
CMyStack<T>::~CMyStack()
{
clear();
}
template<typename T>
CMyStack<T>::CMyStack()
{
pBuff = nullptr;
len = maxSize = 0;
}
#include "stdafx.h"
#include "MyStack.h"
//深度優先搜索
//規則:沿一個方向進行行走,到了岔路口又一次選擇一個方向進行前進,如果碰到死衚衕退回到上一個岔路口重新選擇方向
// 走過的路不會再走,一次走一個節點
//1、準備地圖 (二維數組,用1表示是障礙,不可通行,用0表示可以通行)
#define MAP_ROW 10
#define MAP_COL 10
//2、準備方向
enum Path_Dir{ p_up, p_down,p_left,p_right };
//3、準備一個棧,用來保存搜索過程中可以行走的路徑點信息(在規劃中有後進的先出)
//4、準備一個結構,用來保存每一個路徑點在二維數組的行列值
struct MyPoint
{
int row, col;
};
//5、準備一個輔助數組(1、資源地圖數組不能變;2、對資源地圖要進數據標記)
struct PathNode
{
int val;//保存原始資源的路徑點信息
Path_Dir dir;//當前路徑點的方向標記
bool isFind;//當前路徑點是否被訪問過
};
//準備一個函數,用來判斷參數的座標是否可以通行
bool IsMove(PathNode p[][MAP_COL],int row,int col)
{
if (row < 0 || row >= MAP_ROW || col < 0 || col >= MAP_COL)
return false;//如果越界,不需要進行位置的判斷
if (p[row][col].val != 0 || p[row][col].isFind == true)
return false;//表示當前行列的元素要麼是障礙,要麼已經被訪問過,不能通行
return true;
}
int _tmain(int argc, _TCHAR* argv[])
{
int mapArr[MAP_ROW][MAP_COL] = {
{ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 },
{ 1, 0, 0, 1, 1, 0, 0, 0, 1, 1 },
{ 1, 1, 0, 1, 1, 0, 1, 0, 1, 1 },
{ 1, 1, 0, 0, 0, 0, 1, 0, 1, 1 },
{ 1, 1, 0, 1, 1, 0, 1, 0, 1, 1 },
{ 1, 1, 0, 1, 1, 0, 1, 0, 1, 1 },
{ 1, 1, 0, 1, 1, 0, 1, 0, 1, 1 },
{ 1, 1, 0, 1, 1, 0, 1, 0, 1, 1 },
{ 1, 0, 0, 1, 0, 0, 1, 0, 0, 1 },
{ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }
};
//第6步
PathNode pathArr[MAP_ROW][MAP_COL];
for (int i = 0; i < MAP_ROW; ++i)
{
for (int j = 0; j < MAP_COL; ++j)
{
pathArr[i][j].val = mapArr[i][j];
pathArr[i][j].isFind = false;//表示地圖中的每一個節點都沒有被訪問過
pathArr[i][j].dir = p_up;//表示給地圖中的每一個節點都設定一個初始方向
}
}
//第7步
MyPoint beginPoint = { 1, 1 };
MyPoint endPoint = { 8, 8 };
//第8步:準備一個容器,用來保存可通行路徑點
CMyStack<MyPoint> ms;
ms.push(beginPoint);//把起點壓入到容器中,用來查找後續的結點
//第9步:準備一個輔助座標點,幫助來判斷下一個可通行位置
MyPoint NearPoint = beginPoint;//輔助點先爲起點,然後通過起點設定的方向來對周邊路徑進行搜索
//第10步:開始尋路
while (true)//無法確定循環次數
{
switch (pathArr[NearPoint.row][NearPoint.col].dir)//判斷當前起點在輔助數組中設定的方向
{
case p_up:
//if (pathArr[NearPoint.row - 1][NearPoint.col].val == 0 && //表示當前點的上一行位置是可通行的
// pathArr[NearPoint.row - 1][NearPoint.col].isFind == false)//表示當前點的上一行位置是沒有訪問的
pathArr[NearPoint.row][NearPoint.col].dir = p_left;//當前路口的下一個方向標記出來
if (IsMove(pathArr, NearPoint.row - 1, NearPoint.col))
{
//表示當前座標的上方向能通行
pathArr[NearPoint.row][NearPoint.col].isFind = true;//當前點改爲已訪問
MyPoint temp = { NearPoint.row - 1, NearPoint.col };
ms.push(temp);//壓入這個座標
NearPoint = temp;//把這個上方向可通行的點賦值給輔助點,進行下一次的搜索
}
break;
case p_left:
pathArr[NearPoint.row][NearPoint.col].dir = p_down;//當前路口的下一個方向標記出來
if (IsMove(pathArr, NearPoint.row, NearPoint.col - 1))
{
//表示當前座標的上方向能通行
pathArr[NearPoint.row][NearPoint.col].isFind = true;//當前點改爲已訪問
MyPoint temp = { NearPoint.row, NearPoint.col - 1 };
ms.push(temp);//壓入這個座標
NearPoint = temp;//把這個上方向可通行的點賦值給輔助點,進行下一次的搜索
}
break;
case p_down:
pathArr[NearPoint.row][NearPoint.col].dir = p_right;//當前路口的下一個方向標記出來
if (IsMove(pathArr, NearPoint.row + 1, NearPoint.col))
{
//表示當前座標的上方向能通行
pathArr[NearPoint.row][NearPoint.col].isFind = true;//當前點改爲已訪問
MyPoint temp = { NearPoint.row + 1, NearPoint.col };
ms.push(temp);//壓入這個座標
NearPoint = temp;//把這個上方向可通行的點賦值給輔助點,進行下一次的搜索
}
break;
case p_right://最後一個方向,表示前面三個方向已經搜索完成
if (IsMove(pathArr, NearPoint.row, NearPoint.col + 1))
{
//表示當前座標的上方向能通行
pathArr[NearPoint.row][NearPoint.col].isFind = true;//當前點改爲已訪問
MyPoint temp = { NearPoint.row, NearPoint.col + 1};
ms.push(temp);//壓入這個座標
NearPoint = temp;//把這個上方向可通行的點賦值給輔助點,進行下一次的搜索
}
else
{
//表示當前路口所有方向都不通,要準備退棧
MyPoint tempPoint = ms.getTop();//得到退棧之前的棧頂元素
pathArr[tempPoint.row][tempPoint.col].isFind = true;//要退出棧的這個元素也是已經訪問過了
ms.pop();
if (!ms.empty())//如果棧不爲空
NearPoint = ms.getTop();//得到新的棧頂元素
}
break;
}
if (NearPoint.row == endPoint.row && NearPoint.col == endPoint.col)
break;//找到終點
if (ms.empty())
break;//沒有終點
}
while (!ms.empty())
{
MyPoint tempPoint = ms.getTop();
printf("row = %d, col = %d\n",tempPoint.row,tempPoint.col);
ms.pop();
}
return 0;
}