深度優先搜索C++

圖論
使用棧容器
起始方向不一樣會影響尋路速度和路徑
有多條路徑的情況下無法找到最短路徑
用於知道終點的方位的場景
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;
}
發佈了52 篇原創文章 · 獲贊 5 · 訪問量 4417
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章