对于图这种数据结构,最基础的就是它的遍历方式。
在书上看到一段话:对于无权的图,使用广搜就可以获得其路径,对于有权图就不可以。
无权的图,就相当于每条边的权为1。迷宫就是最简单的一种无权图,每一步都是一个节点,节点和节点之间的边长都为1。
为了验证这个思想,自己定义一个迷宫,通过BFS获得可以走出去的所有路径和最短的路径。
BFS就是以一个起点,配合队列,向四面八方进行搜索,搜过过了就更改标记表示已经走过了。
1 #include
2 #include
3 #include
4 #include
5 #include
6 #include
7 #include
8 #include
9
10 using namespacestd;11
12 typedef structpoint{13 intx;14 inty;15 point *previous;16 intstep;17 } point;18
19 point dir[4] ={20 { 0, 1, NULL, 0},21 { 1, 0, NULL, 0},22 { 0, -1, NULL, 0},23 { -1, 0, NULL, 0},24 };25
26 //只有0位置可以走,到数组边缘就是走出迷宫。27 //输出最短的路径和最短步数
28 int map[8][8] ={29 { 1, 0, 1, 1, 1, 1, 1, 1},30 { 1, 0, 0, 0, 0, 0, 0, 1},31 { 1, 0, 1, 1, 1, 1, 0, 1},32 { 1, 0, 0, 0, 0, 1, 0, 0},33 { 1, 1, 1, 1, 0, 0, 1, 1},34 { 1, 1, 1, 1, 1, 0, 1, 1},35 { 1, 1, 0, 0, 0, 0, 1, 1},36 { 1, 1, 0, 1, 1, 1, 1, 1},37 };38
39 void PrintAllPath(point *p)40 {41 int shortest = p->step;42
43 cout << "可行短路径为:";44 while (p->previous !=NULL)45 {46 cout << "(" << p->x << "," << p->y << ")";47 p = p->previous;48 }49 cout << "(" << p->x << "," << p->y << ")" <
53 voidBFS(point startPoint)54 {55 queueq;56 q.push(startPoint);57 point cur;58
59 while (!q.empty())60 {61 cur =q.front();62 q.pop();63 map[cur.x][cur.y] = 1;64
65 for (int i = 0; i < 4; i++)66 {67 point nxt{ cur.x + dir[i].x, cur.y + dir[i].y, NULL, 0};68 if (nxt.x >= 0 && nxt.x < 8 && nxt.y >= 0 && nxt.y < 8 && map[nxt.x][nxt.y] == 0)69 {70 point *tmp = newpoint;71 memcpy(tmp, &cur, sizeof(point));72 nxt.previous =tmp;73 nxt.step = cur.step + 1;74 map[nxt.x][nxt.y] = 1;75
76 if (nxt.x == 0 || nxt.x == 7 || nxt.y == 0 || nxt.y == 7)77 {78 PrintAllPath(&nxt);79
80 //这句话注释则输出所有路径,不注释是最短路径81 //return;
82 }83 q.push(nxt);84 }85 }86 }87 }88
89 intmain()90 {91 point startPoint{ 0, 1, NULL, 0};92 BFS(startPoint);93
94 return 0;95 }
结果,上图:
广搜很好实现。在设计点坐标时,需要几个参量:
x,y;
上一个节点x,y;
已经走的步数。
配合这个左边点数据结构不断进入队列,当此节点碰到边界时则走出去,函数返回则是最短路径。
不return,则会输出所有的路径和步数。
// Test.cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;
typedef struct point{
int x;
int y;
point *previous;
int step;
} point;
point dir[4] = {
{ 0, 1, NULL, 0 },
{ 1, 0, NULL, 0 },
{ 0, -1, NULL, 0 },
{ -1, 0, NULL, 0 },
};
//只有0位置可以走,到数组边缘就是走出迷宫。
//输出最短的路径和最短步数
int map[8][8] = {
{ 1, 0, 1, 1, 1, 1, 1, 1 },
{ 1, 0, 0, 0, 0, 0, 0, 1 },
{ 1, 0, 1, 1, 1, 1, 0, 1 },
{ 1, 0, 0, 0, 0, 1, 0, 0 },
{ 1, 1, 1, 1, 0, 0, 1, 1 },
{ 1, 1, 1, 1, 1, 0, 1, 1 },
{ 1, 1, 0, 0, 0, 0, 1, 1 },
{ 1, 1, 0, 1, 1, 1, 1, 1 },
};
void PrintAllPath(point *p)
{
int shortest = p->step;
cout << "可行短路径为:";
while (p->previous != NULL)
{
cout << "(" << p->x << "," << p->y << ")";
p = p->previous;
}
cout << "(" << p->x << "," << p->y << ")" << endl;
cout << "路径长度为:" << shortest << endl;
}
void BFS(point startPoint)
{
queue q;
q.push(startPoint);
point cur;
while (!q.empty())
{
cur = q.front();
q.pop();
map[cur.x][cur.y] = 1;
for (int i = 0; i < 4; i++)
{
point nxt{ cur.x + dir[i].x, cur.y + dir[i].y, NULL, 0 };
if (nxt.x >= 0 && nxt.x < 8 && nxt.y >= 0 && nxt.y < 8 && map[nxt.x][nxt.y] == 0)
{
point *tmp = new point;
memcpy(tmp, &cur, sizeof(point));
nxt.previous = tmp;
nxt.step = cur.step + 1;
map[nxt.x][nxt.y] = 1;
if (nxt.x == 0 || nxt.x == 7 || nxt.y == 0 || nxt.y == 7)
{
PrintAllPath(&nxt);
//这句话注释则输出所有路径,不注释是最短路径
//return;
}
q.push(nxt);
}
}
}
}
int main()
{
point startPoint{ 0, 1, NULL, 0 };
BFS(startPoint);
system("pause");
return 0;
}