C语言使用深度优先搜索算法解决迷宫问题(堆栈)

C语言使用深度优先搜索算法解决迷宫问题 (堆栈)

什么是深度优先搜索算法

深度优先搜索算法 (DFS) 是一种常见的搜索算法。深度优先搜索算法像探险家一样从起点往前走,如果碰到了障碍物就返回,再尝试另一条路径。这个过程就是递归。

在深度优先搜索算法中,我们需要利用堆栈结构来保存需要回溯的节点。在搜索过程中,我们访问每个相邻的顶点,并将已经访问过的标记为已访问。然后我们继续访问相邻的节点,并标记已访问,如此下去,直到找到我们需要的节点,或是到达终点。

迷宫问题

假设我们有一个 n 行 m 列的迷宫,为了通行方便,我们将道路和墙都画成了矩阵,矩阵里的数字表示他的属性。其中,0 表示道路,1 表示墙,2 表示起点,3 表示终点。

我们需要使用深度优先搜索算法,在这个迷宫中找出一条从起点到终点的路径。

以下是一个 6x6 的迷宫示例:

1 1 1 1 1 1
1 0 0 0 0 1
1 0 1 1 0 1
1 0 0 1 0 1
1 0 0 0 0 1
1 1 1 1 1 1

起点为 (1, 1),终点为 (4, 4)。

解决迷宫问题

我们可以使用一个二维数组来表示迷宫,并初始化起点和终点的坐标:

#define MAX_ROW 6
#define MAX_COL 6
int maze[MAX_ROW][MAX_COL] = {
    {1, 1, 1, 1, 1, 1},
    {1, 0, 0, 0, 0, 1},
    {1, 0, 1, 1, 0, 1},
    {1, 0, 0, 1, 0, 1},
    {1, 0, 0, 0, 0, 1},
    {1, 1, 1, 1, 1, 1}
};

// 起点和终点
int start_row = 1, start_col = 1;
int end_row = 4, end_col = 4;

我们还需要一个 stack 数据结构,用于保存需要回溯的节点:

#define MAX_SIZE 100
typedef struct {
    int row;
    int col;
} element;

// 定义堆栈
element stack[MAX_SIZE];
int top = -1;

// 入栈操作
void push(int row, int col) {
    element e = {row, col};
    stack[++top] = e;
}

// 出栈操作
element pop() {
    return stack[top--];
}

// 判断堆栈是否为空
int is_empty() {
    return top == -1;
}

在我们开启搜索之前,我们需要将起点压入堆栈,并将起点标记为已访问:

// 标记已访问
int visited[MAX_ROW][MAX_COL] = {0};
visited[start_row][start_col] = 1;

// 将起点入栈
push(start_row, start_col);

接下来,我们需要编写一个函数来搜索迷宫。这个函数的任务是,从堆栈中取出一个节点,检查它是否是终点,如果不是,则检查它的四个相邻节点是否可以访问。如果可以访问,则将这个节点压入堆栈,并标记为已访问。

如果堆栈为空,说明我们已经走到了迷宫的边缘,但是没有找到终点。这个时候,我们需要返回 0,表示没有找到出路。

int search() {
    while (!is_empty()) {
        element e = pop();

        // 判断是否到达终点
        if (e.row == end_row && e.col == end_col) {
            printf("(%d, %d)\n", e.row, e.col);
            return 1;
        }

        // 取出当前节点的四个相邻节点,如果可以访问,则入栈
        if (e.row - 1 >= 0 && maze[e.row - 1][e.col] == 0 && !visited[e.row - 1][e.col]) {
            element adj = {e.row - 1, e.col};
            push(adj.row, adj.col);
            visited[adj.row][adj.col] = 1;
        }
        if (e.col - 1 >= 0 && maze[e.row][e.col - 1] == 0 && !visited[e.row][e.col - 1]) {
            element adj = {e.row, e.col - 1};
            push(adj.row, adj.col);
            visited[adj.row][adj.col] = 1;
        }
        if (e.row + 1 < MAX_ROW && maze[e.row + 1][e.col] == 0 && !visited[e.row + 1][e.col]) {
            element adj = {e.row + 1, e.col};
            push(adj.row, adj.col);
            visited[adj.row][adj.col] = 1;
        }
        if (e.col + 1 < MAX_COL && maze[e.row][e.col + 1] == 0 && !visited[e.row][e.col + 1]) {
            element adj = {e.row, e.col + 1};
            push(adj.row, adj.col);
            visited[adj.row][adj.col] = 1;
        }

        printf("(%d, %d)\n", e.row, e.col);
    }
    return 0;
}

最后,我们只需要在主函数中调用 search 函数即可:

int main() {
    if (search()) {
        printf("找到了出路\n");
    } else {
        printf("没有出路\n");
    }
    return 0;
}

示例说明

假设我们要在以下这个迷宫中寻找一条从起点 (1, 1) 到终点 (4, 4) 的路径:

1 1 1 1 1
1 0 0 0 1
1 1 0 0 1
1 0 0 0 1
1 1 1 1 1

我们可以使用上面的代码进行搜索,得到的输出为:

(1, 1)
(2, 1)
(3, 1)
(4, 1)
(4, 2)
(4, 3)
(3, 3)
(2, 3)
(1, 3)
(1, 2)
(2, 2)
(3, 2)
(4, 4)
找到了出路

说明我们已经成功找到了一条从起点到终点的路径。

再举一个例子,假设我们要在以下这个迷宫中寻找一条从起点 (1, 1) 到终点 (5, 5) 的路径:

1 1 1 1 1 1
1 0 1 0 0 1
1 0 1 0 1 1
1 0 1 0 0 1
1 0 0 0 1 1
1 1 1 1 1 1

我们可以使用上面的代码进行搜索,得到的输出为:

(1, 1)
(2, 1)
(3, 1)
(4, 1)
(4, 2)
(4, 3)
(4, 4)
(5, 4)
(5, 5)
找到了出路

说明我们已经成功找到了一条从起点到终点的路径。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:C语言使用深度优先搜索算法解决迷宫问题(堆栈) - Python技术站

(0)
上一篇 2023年5月22日
下一篇 2023年5月22日

相关文章

  • 如何理解C++指针常量和常量指针

    下面给你详细讲解如何理解C++指针常量和常量指针。 1. 指针常量 1.1 概念介绍 指针常量是指一个指针被定义为常量(值不能被改变),而指针所指向的变量的值可以变化。在定义指针常量时,必须把指针初始化为某个地址。 1.2 示例说明 以下是一个指针常量的示例: #include <iostream> using namespace std; in…

    C 2023年5月23日
    00
  • C++随机点名生成器实例代码(老师们的福音!)

    首先,我们需要明确实现这个随机点名生成器的基本思路。我们需要一个名单,这个名单中包含每个学生的姓名信息,然后从这个名单中随机选择一个学生进行点名。因此,我们需要把这个名单存储在程序中,并且要有一个随机数函数来随机选择学生。 接下来,我们需要定义一个学生类,用来存储学生的姓名信息。在这个类中,我们需要定义公有的姓名属性,并且需要定义构造函数和析构函数。 在主函…

    C 2023年5月30日
    00
  • 如何在在Vue3中使用markdown 编辑器组件

    以下是在Vue3中使用markdown编辑器组件的攻略: 安装markdown编辑器组件 我们可以使用vue-markdown-editor组件,这是一个基于Vue3的markdown编辑器组件。 在终端中输入下列命令安装: npm install vue3-markdown-editor –save 引入组件 在Vue3项目中,可以使用以下代码引入组件:…

    C 2023年5月23日
    00
  • Linux中使用C语言的fork()函数创建子进程的实例教程

    下面是详细讲解创建子进程的实例教程。 什么是子进程? 在Linux系统中,一个进程可以创建其他进程。被创建的进程称为子进程,而新创建进程的进程称为父进程。子进程继承了父进程的所有属性和资源,包括进程ID、打开的文件描述符、信号处理方式等。 如何创建子进程? Linux中使用C语言提供了 fork() 函数来创建子进程。fork()函数是一个系统调用,调用后会…

    C 2023年5月23日
    00
  • C语言用malloc创建一维数组

    当我们在C语言中需要动态分配一维数组时,我们可以使用malloc函数来进行分配。malloc函数会返回一个void类型的指针,我们需要将它强制类型转换成所需要的数组类型指针,以便后续的使用。 下面是使用malloc创建一维数组的完整攻略: 1. 分配内存空间 我们可以使用malloc函数来分配内存空间,其函数原型为: #include <stdlib.…

    C 2023年5月9日
    00
  • C++实现校园导游系统

    C++实现校园导游系统攻略 系统概述 本系统利用C++实现了校园导游的功能,用户可以在系统中选择要参观的景点,并得到相关的信息如景点介绍、地址、开放时间等。同时,用户还可以在地图上查看各个景点的位置和路线,方便用户进行导览。 功能模块 本系统主要分为以下模块: 景点数据读入模块,用于从文件中将景点信息读入内存。 景点信息显示模块,用于在控制台上显示景点信息。…

    C 2023年5月23日
    00
  • C语言怎么获得进程的PE文件信息

    要获取进程的PE文件信息,可以使用Windows的API函数和一些常用的数据结构。 首先需要使用OpenProcess函数打开目标进程,该函数会返回目标进程的句柄,用于后续的操作。然后再使用GetModuleInformation函数获取目标进程的所有模块信息,包括PE文件的基址、大小等信息。最后需要使用CloseHandle关闭进程句柄以释放资源。 以下是…

    C 2023年5月23日
    00
  • c++ vector对象相关总结

    C++ Vector对象相关总结 什么是Vector? Vector是C++标准库中的一个动态数组容器,可自动管理其大小(即内存分配和释放),支持快速随机访问。 动态数组顾名思义就是可以动态增长的数组。和普通数组不同之处在于,普通数组在定义时需要明确指定数组大小,而动态数组则可以在运行时根据需要改变大小。 Vector的使用方法 首先需要包含头文件。 1.定…

    C 2023年5月22日
    00
合作推广
合作推广
分享本页
返回顶部