BFS(广度优先)

问题描述:给定一副地图,一个开始坐标,一个结束坐标,寻找一条可以从开始坐标到结束坐标的最短路径

定义数据类型如下:

typedef struct node {
    int step=0;//从起点到该点的步数
    int x;
    int y;
} path, node;

问题分析:通过广度优先的思想,借助队列的结构,一层一层标记地图上从起点到各个点的距离,算出最短距离,判断每个点的距离是否连续,找到终点即为最短的路径。先压入队列起点,弹出队列头部元素,通过方向数组判断方向,在将其相邻的元素压入队列,标记步数,以此循环

核心代码

int v[100][100];//判断是否走过
//方向数组
int dx[4] = { 0,1,0,-1 };
int dy[4] = { 1,0,-1,0 };
​
void bfs_maze(node start, node end) {
    LinkQueue q = InitQueue();//初始化队列
    start.step = 1;//将起点标记为1
    q=Enqueue(q, start);//压入队列
    v[start.x][start.y] = 1;//标记该点为以走过
    int flag = 0;//判断是否可通的标记
    while (!Empty(q))
    {
        node front_item;//临时变量暂存队首元素
        q=DelQueue(q, &front_item);//删除队首元素
        if (front_item.x==end.x&&front_item.y==end.y)//找到的终点
        {
            flag = 1;
            break;
        }
        for (int i = 0; i < 4; i++)
        {
            int tempx = front_item.x + dx[i];//通过方向数组的下一个横坐标
            int tempy = front_item.y + dy[i];//通过方向数组的下一个纵坐标
            if (tempx >= 0 && tempx < len && tempy >= 0 && tempy < len) {//是否越界
                if (maze[tempx][tempy]==1&&v[tempx][tempy]==0)//该点从未走过且为地图上可通的点
                {
                    node temp;
                    temp.x = tempx;
                    temp.y = tempy;
                    temp.step = front_item.step + 1;
                    maze[tempx][tempy] = temp.step;//标记步数
                    q=Enqueue(q, temp);//压入队列中
                    v[tempx][tempy] = 1;//该点已走过
                }
            }
        }
​
    }
    if (flag==0)
    {
        printf("不可通!");
    }
}

完整代码如下:

#include<stdio.h>
#include<malloc.h>
typedef struct node {
    int step=0;
    int x;
    int y;
} path, node;
​
typedef struct Qnode
{
    node data;//其中数据域data为抽象元素类型
    struct Qnode* next;//其中next为指针类型 
}Qnode, * QueuePtr;//其中,Qnode为结点类型, QueuePtr:指向Qnode的指针类型
​
typedef struct
{
    Qnode* front;//头指针
    Qnode* rear;//尾指针 
}LinkQueue;//链式队列类型 
​
//生成空队列算法:初始化队列 
#define LENG sizeof(Qnode)//求结点所占的单元数
LinkQueue InitQueue()//生成仅带表头结点的空队列Q
{
    LinkQueue Q;//说明变量Q
    Q.front = Q.rear = (QueuePtr)malloc(LENG);//生成表头结点
    Q.front->next = NULL;//表头结点的next为空指针
    return Q;//返回Q的值 
}
​
​
//(非)空队列时插入新元素x 
LinkQueue Enqueue(LinkQueue Q, node e)
{
    Qnode* p;//说明变量p
    p = (Qnode*)malloc(LENG);//生成新元素结点
    p->data = e;//装入元素e
    p->next = NULL;//为队尾结点
    Q.rear->next = p;//插入新结点
    Q.rear = p;//修改尾指针
    return Q;//返回Q的新值 
}
//链式队列的出队算法 
LinkQueue DelQueue(LinkQueue Q, node* e)
{
    Qnode* p;//声明变量p
    if (Q.front == Q.rear)//若原队列为空
    {
        printf("Empty queue");//空队列
        return Q;
    }
    p = Q.front->next;//p指向要删除的队头结点
    (*e) = p->data;//取出元素
    Q.front->next = p->next;//删除队头结点
    if (Q.rear == p)//若原队列只有1个结点
    {
        Q.rear = Q.front;//修改尾指针 
    }
    free(p);//释放被删除的空间
    return Q;//返回出队后的Q 
}
​
bool Empty(LinkQueue& q) {
    if (q.rear==q.front)
    {
        return true;
    }
    return false;
}
int dx2[4] = { 1,0,0,-1 };
int dy2[4] = { 0,1,-1,0 };
​
int maze[6][6] = {
{0,1,0,0,0,0},
{0,1,1,1,1,0},
{0,1,0,1,0,0},
{0,1,0,1,1,0},
{0,1,1,0,1,0},
{0,0,1,1,1,0} };
int len = 6;
int v[100][100];//判断是否走过
//方向数组
int dx[4] = { 0,1,0,-1 };
int dy[4] = { 1,0,-1,0 };
​
void bfs_maze(node start, node end) {
    LinkQueue q = InitQueue();
    start.step = 1;
    q=Enqueue(q, start);
    v[start.x][start.y] = 1;
    int flag = 0;
    while (!Empty(q))
    {
        node front_item;
        q=DelQueue(q, &front_item);
        if (front_item.x==end.x&&front_item.y==end.y)
        {
            flag = 1;
            break;
        }
        for (int i = 0; i < 4; i++)
        {
            int tempx = front_item.x + dx[i];
            int tempy = front_item.y + dy[i];
            if (tempx >= 0 && tempx < len && tempy >= 0 && tempy < len) {
                if (maze[tempx][tempy]==1&&v[tempx][tempy]==0)
                {
                    node temp;
                    temp.x = tempx;
                    temp.y = tempy;
                    temp.step = front_item.step + 1;
                    maze[tempx][tempy] = temp.step;
                    q=Enqueue(q, temp);
                    v[tempx][tempy] = 1;
                }
            }
        }
​
    }
    if (flag==0)
    {
        printf("不可通!");
    }
}
​
void printMaze() {
    for (int i = 0; i < 6; i++)
    {
        for (int j = 0; j < 6; j++) {
            printf("%d ", maze[i][j]);
        }
        printf("\n");
    }
    printf("\n");
}
​
void printMaze2(node start, node end) {
    while (start.step != end.step) {
        start.step++;
        for (int i = 0; i < 4; i++)
        {
            int tmpx = start.x + dx2[i];
            int tmpy = start.y + dy2[i];
            if (tmpx >= 0 && tmpx < len && tmpy >= 0 && tmpy < len) {
                if (maze[tmpx][tmpy] == start.step) {
                    printf("%d %d\n", tmpx, tmpy);
                    start.x = tmpx;
                    start.y = tmpy;
                    break;
                }
            }
        }
    }
}
int main() {
    node start, end;
    start.x = 0;
    start.y = 1;
    end.x = 5;
    end.y = 2;
    printMaze();
    bfs_maze(start, end);
    printMaze();
    start.step = maze[start.x][start.y];
    end.step = maze[end.x][end.y];
    printMaze2(start,end);
    //printRoad(start);
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值