• 图及深度优先搜索


    图及图的搜索算法

    一、图论

    图论是数学的一个分支,它以图为研究对象

    图论中的图是由若干给定的点及连接两点的线所构成的图形,这种图形通常同来描述事物之间的某种特定关系,用点代表事物,用连接两点的线表示相应两个事物之间有这种关系

    二、图的结构

    非线性结构

    有n个直接前趋,n个直接后继

    三、图的组成

    由两部分组成,一部分叫点的集合,另一部分叫边的集合

    四、图的分类

    1.无向图,图中的边是节点的无序对(即两节点不分谁是起始点,谁是终止点),则此图称为无向图。通常有圆括号表示无向边

    2.有向图。图中边是节点的有序对,则称此图为有向图。有向边又称为弧,通常用尖括号表示一条有向边

    3.有向完全图与无向完全图。在图中的任何一个点,和其他所有的点都有边连接

    五、深度优先

    1.规则

    沿着一个固定的方向进行行走,到了岔路口才又一次选择方向,如果碰到了死胡同退回上一个岔路口重新选择方向,走过的路就不会再重新走,一次走一个岔路口

    注意:因为方向设定不一样,可能最终找到的路径是不一样的。跟默认的方向有关,默认的方向选的好,那么可能路径就比较短,如果选的不好,有可能路径就很远

    方向的设置会极大的影响寻路的效率

    六、深度优先搜索代码实现

    #include<iostream>
    using namespace std;
    
    //1.有图(二维数组)
    #define MAP_ROW 10
    #define MAP_COL 10
    
    //准备一个结构来表示路径点的类型
    struct MyPoint
    {
    	int row, col; 
    };
    
    //准备一个方向,表示搜索的行进方向
    enum PathDir
    {
    	p_up,p_down,p_left,p_right
    };
    
    //4.准备一个数据结构用来保存搜索后的路径点数据
    #include<stack>
    
    
    //5.准备一个辅助地图,为搜索做辅助操作,避免修改资源
    struct PathNode
    {
    	int val;//用来保存原始资源的路径点信息
    	PathDir dir;//在当前节点上搜索方向
    	bool isFind;//标记是否已访问
    };
    
    
    bool checkPoint(PathNode p[][MAP_COL], int row, int col)
    {
    	//判断当前row,col是否越界
    	if (row < 0 || row >= MAP_COL || col < 0 || col >= MAP_COL)
    		return false;
    
    	//判断当前位置为障碍或已被访问过
    	if (p[row][col].val != 0 || p[row][col].isFind)
    		return false;
    	return true;
    }
    
    int main()
    {
    	//点的集合
    	int arr[MAP_ROW][MAP_COL] = {
    		{1,1,0,1,1,1,1,1,1,1},
    		{1,1,0,1,1,1,1,1,1,1},
    		{1,1,0,0,0,0,0,0,1,1},
    		{1,1,1,0,1,0,1,0,1,1},
    		{1,1,1,0,1,0,1,0,1,1},
    		{1,1,1,0,1,0,1,0,1,1},
    		{1,1,0,0,1,0,1,0,1,1},
    		{1,1,0,1,1,0,1,1,1,1},
    		{1,1,0,0,1,0,1,1,1,1},
    		{1,1,1,1,1,1,1,1,1,1},
    	};
    	//准备一个结构体数组
    	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 = arr[i][j];
    
    			//表示所有的路径点都没有被访问
    			pathArr[i][j].isFind = false;
    
    			//设置每一个坐标点的初始方向为上
    			pathArr[i][j].dir = p_up;
    		}
    	}
    	//辅助数组准备完成
    
    	//先保存起点和终点信息
    	MyPoint beginPoint = { 0,2 };
    	MyPoint endPoint = { 6,7 };
    
    	//用栈容器保存起点信息
    	stack<MyPoint> s;
    	s.push(beginPoint);//先将起点信息压进栈
    
    
    	//因为要用起点来进行搜索,但是起点信息不能改变,所以要定义一个辅助坐标,用来找其他位置
    	MyPoint currentPoint = beginPoint;
    
    
    
    	//然后开始搜索
    	while (true)//不知道怎么结束,就一直循环
    	{  
    		switch (pathArr[currentPoint.row][currentPoint.col].dir)
    		{
    			//就是寻路方向:上--》下--》左--》右
    		case p_up:
    			pathArr[currentPoint.row][currentPoint.col].dir = p_down;//这一行表示,如果不可通行的话,还是要改变方向,因为你不能确定你下面的路一直是通的,如果下面的路不通的话,往回退到这里,就不用走以前走过的路了
    			if (checkPoint(pathArr, currentPoint.row - 1, currentPoint.col))
    			{
    				//表示可通行
    
    				//要标记当前路径点已经被访问了
    				pathArr[currentPoint.row][currentPoint.col].isFind = true;
    				//改变当前路径点寻路方向,表示如果通行之后,再次回退到这个路径点,下一次的搜索方向
    				//pathArr[currentPoint.row][currentPoint.col].dir = p_down;
    
    				//如果可以通行的话,就要把这个可以通行的路径点信息保存到栈中,所以要用一个临时变量来保存这个路径点
    				MyPoint tempPoint = { currentPoint.row - 1, currentPoint.col };
    				//入栈
    				s.push(tempPoint);
    				//保存完之后,还要改变当前寻路点的信息
    				currentPoint = tempPoint;
    			}
    			//else
    			//{
    			//	//表示不可通行
    			//	//不可通行就要改变方向
    			//	pathArr[currentPoint.row][currentPoint.col].dir = p_down;
    			//}
    			break;
    		case p_down:
    			pathArr[currentPoint.row][currentPoint.col].dir = p_left;
    			if (checkPoint(pathArr, currentPoint.row + 1, currentPoint.col))
    			{
    				pathArr[currentPoint.row][currentPoint.col].isFind = true;
    				MyPoint tempPoint = { currentPoint.row + 1, currentPoint.col };
    				s.push(tempPoint);
    				currentPoint = tempPoint;
    			}
    			break;
    		case p_left:
    			pathArr[currentPoint.row][currentPoint.col].dir = p_right;
    			if (checkPoint(pathArr, currentPoint.row , currentPoint.col-1))
    			{
    				pathArr[currentPoint.row][currentPoint.col].isFind = true;
    				MyPoint tempPoint = { currentPoint.row, currentPoint.col-1 };
    				s.push(tempPoint);
    				currentPoint = tempPoint;
    			}
    			break;
    		case p_right:
    			if (checkPoint(pathArr, currentPoint.row, currentPoint.col+1))
    			{
    				pathArr[currentPoint.row][currentPoint.col].isFind = true;
    				MyPoint tempPoint = { currentPoint.row, currentPoint.col+1 };
    				s.push(tempPoint);
    				currentPoint = tempPoint;
    			}
    			else
    			{
    				//并不是右方向才加else,而是四个搜索方向上的最后一个方向上才加else
    				//出栈,就是说不能通行的话,就只能将路径点弹出栈,然后往后面寻路
    				//退栈之前,要将栈顶的元素标记为已访问
    				MyPoint tempPoint = s.top();
    				pathArr[tempPoint.row][tempPoint.col].isFind = true;
    				s.pop();
    				//让当前路径点指向这个栈的最后一个元素--路径点
    				
    				//empty()如当前堆栈为空,empty() 函数 返回 true 否则返回false.
    				if(!s.empty())//栈不为空才能得到栈顶元素
    					currentPoint = s.top();
    			}
    			break;
    		default:
    			break;
    		}
    		if (currentPoint.row == endPoint.row&&currentPoint.col == endPoint.col)
    			break;//退出while循环
    		if (s.empty())
    			break;//就是说,没有找到这个终点,把元素压进栈后,又把所有的元素弹出来了
    	}
    
    	//将路径打印出来
    	while (!s.empty())//栈不为空才能打印
    	{
    		MyPoint tempPoint = s.top();
    		//从栈顶开始打印
    		printf("row=%d,	col=%d
    ", tempPoint.row, tempPoint.col);
    		s.pop();
    	}
    
    
    	return 0;
    }
    
  • 相关阅读:
    Android开发学习之路-使用Handler和Message更新UI
    Android开发学习之路-Service和Activity的通信
    Android开发学习之路-自定义ListView(继承BaseAdapter)
    URI、URL、URN
    理解 node.js 的事件循环
    创建hexo风格的markdown页面
    heroku
    js通过沿着作用域链还是原型链查找变量
    浏览器中实现3D全景浏览
    数据可视化图表ECharts
  • 原文地址:https://www.cnblogs.com/Kissfly123/p/14637935.html
Copyright © 2020-2023  润新知