数据结构与算法-图论-DFS/BFS

图搜索算法在数据结构与算法领域中非常关键,用于在图形数据结构中搜索节点或路径。图是由节点(也称为顶点)以及连接这些节点的边组成的。在本文中,我们将详细探讨两种基础的图搜索算法:深度优先搜索(DFS)和广度优先搜索(BFS),并提供相应的C语言代码示例。

1.深度优先搜索(DFS)

深度优先搜索(DFS)是一种遍历或搜索树或图的算法。DFS 探索尽可能深的分支路径,直到无法继续,然后回溯以探索未被访问的路径。

特点

  • 使用栈实现,可以是显式的数据结构栈,或者利用递归调用的隐式栈。
  • 常用于路径搜索,解决连通性问题和排序问题。

C 语言代码示例

假设图以邻接表形式给出,这里使用结构体和指针来定义图的结构。

实现一个完整的深度优先搜索(DFS)算法,我们需要添加图的创建、边的添加以及DFS本身的实现。以下代码段将完成这些部分,实现图的创建、添加边,并利用DFS遍历图:

#include <stdio.h>
#include <stdlib.h>// 定义图的节点
typedef struct node {int vertex;struct node* next;
} Node;// 定义图结构
typedef struct {int numVertices;Node** adjLists;int* visited;
} Graph;// 创建节点
Node* createNode(int v) {Node* newNode = malloc(sizeof(Node));newNode->vertex = v;newNode->next = NULL;return newNode;
}// 创建图
Graph* createGraph(int vertices) {Graph* graph = malloc(sizeof(Graph));graph->numVertices = vertices;graph->adjLists = malloc(vertices * sizeof(Node*));graph->visited = malloc(vertices * sizeof(int));int i;for (i = 0; i < vertices; i++) {graph->adjLists[i] = NULL;graph->visited[i] = 0;}return graph;
}// 添加边
void addEdge(Graph* graph, int src, int dest) {// 添加从src到dest的边Node* newNode = createNode(dest);newNode->next = graph->adjLists[src];graph->adjLists[src] = newNode;// 由于是无向图,添加从dest到src的边newNode = createNode(src);newNode->next = graph->adjLists[dest];graph->adjLists[dest] = newNode;
}// 深度优先搜索实现
void DFS(Graph* graph, int vertex) {Node* adjList = graph->adjLists[vertex];Node* temp = adjList;graph->visited[vertex] = 1;printf("已访问 %d\n", vertex);while (temp != NULL) {int connectedVertex = temp->vertex;if (graph->visited[connectedVertex] == 0) {DFS(graph, connectedVertex);}temp = temp->next;}
}int main() {Graph* graph = createGraph(6);addEdge(graph, 0, 1);addEdge(graph, 0, 2);addEdge(graph, 1, 2);addEdge(graph, 1, 3);addEdge(graph, 2, 4);addEdge(graph, 3, 4);addEdge(graph, 3, 5);addEdge(graph, 4, 5);DFS(graph, 0);  // 从顶点0开始深度优先搜索return 0;
}

代码说明

  1. 图的结构:使用邻接表来表示图,其中每个节点包含顶点编号和指向下一个邻接顶点的指针。
  2. 创建图和节点:提供函数来创建图和其节点。
  3. 添加边:因为是无向图,所以每添加一个方向的边时,也要添加反方向的边。
  4. DFS函数:使用递归实现深度优先搜索。开始时,标记当前节点为已访问,并递归地访问所有未被访问的邻接节点。

这段代码能够遍历给定图的所有顶点,显示每个访问的顶点。这是深度优先搜索常见的用法,可以用于检测图的连通性、查找图中的路径等。

2. 广度优先搜索(BFS)

广度优先搜索(BFS)是另一种图的遍历算法,它从根节点开始,逐层遍历图中的所有节点,先访问近邻节点,再访问更远的节点。

特点

  • 使用队列实现。
  • 常用于找到最短路径或任何层次遍历的场景。

C 语言代码示例

基于上面的图结构,我们可以实现 BFS:

以下是完整的广度优先搜索(BFS)的C语言实现,包括定义图结构、队列的操作函数(入队、出队、判断是否为空)以及广度优先搜索的具体实现。我们将继续从之前的代码段扩展,完善队列的操作和图的遍历逻辑。

C 语言代码示例

#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>// 定义队列结构
typedef struct queue {int items[100];int front;int rear;
} Queue;// 创建队列
Queue* createQueue() {Queue* q = malloc(sizeof(Queue));q->front = -1;q->rear = -1;return q;
}// 检查队列是否为空
bool isEmpty(Queue* q) {if(q->rear == -1)return true;elsereturn false;
}// 入队
void enqueue(Queue* q, int value) {if(q->rear == 99)printf("队列已满.\n");else {if(q->front == -1)q->front = 0;q->rear++;q->items[q->rear] = value;}
}// 出队
int dequeue(Queue* q) {int item;if(isEmpty(q)) {printf("队列为空.\n");item = -1;} else {item = q->items[q->front];q->front++;if(q->front > q->rear) {q->front = -1;q->rear = -1;}}return item;
}typedef struct node {int vertex;struct node* next;
} Node;typedef struct {int numVertices;Node** adjLists;int* visited;
} Graph;Node* createNode(int v) {Node* newNode = malloc(sizeof(Node));newNode->vertex = v;newNode->next = NULL;return newNode;
}Graph* createGraph(int vertices) {Graph* graph = malloc(sizeof(Graph));graph->numVertices = vertices;graph->adjLists = malloc(vertices * sizeof(Node*));graph->visited = malloc(vertices * sizeof(int));for(int i = 0; i < vertices; i++) {graph->adjLists[i] = NULL;graph->visited[i] = 0;}return graph;
}void addEdge(Graph* graph, int src, int dest) {Node* newNode = createNode(dest);newNode->next = graph->adjLists[src];graph->adjLists[src] = newNode;newNode = createNode(src);newNode->next = graph->adjLists[dest];graph->adjLists[dest] = newNode;
}void BFS(Graph* graph, int startVertex) {Queue* queue = createQueue();graph->visited[startVertex] = 1;enqueue(queue, startVertex);while(!isEmpty(queue)) {int currentVertex = dequeue(queue);printf("已访问 %d\n", currentVertex);Node* temp = graph->adjLists[currentVertex];while(temp) {int adjVertex = temp->vertex;if(graph->visited[adjVertex] == 0) {graph->visited[adjVertex] = 1;enqueue(queue, adjVertex);}temp = temp->next;}}
}int main() {Graph* graph = createGraph(6);addEdge(graph, 0, 1);addEdge(graph, 0, 2);addEdge(graph, 1, 3);addEdge(graph, 1, 4);addEdge(graph, 2, 5);BFS(graph, 0);return 0;
}

说明

这段代码首先定义了一个图和一个队列,然后实现了广度优先搜索(BFS)。在BFS中,我们首先将起始顶点放入队列,并标记为已访问。然后,我们依次从队列中取出顶点,并访问其所有未访问的邻接点,将它们加入队列并标记为已访问。这个过程重复进行,直到队列为空。通过这种方式,BFS可以按层次访问图中的所有顶点。

在实际生活应用中,深度优先搜索(DFS)可用于解决如解迷宫问题。这个案例使用深度优先搜索算法探索从迷宫的入口到出口的路径。迷宫可以视为一个由格子组成的网格,其中一些格子是可通过的,而其他格子则可能被墙阻挡。

3. C 语言实现 DFS 解迷宫

以下是用C语言实现的迷宫探索代码。我们将使用深度优先搜索来尝试每一条可能的路径,直到找到出口。如果找到出口,我们将打印出一条路径。

C语言代码示例

#include <stdio.h>
#include <stdbool.h>#define ROW 5
#define COL 5// 迷宫地图,0可走,1不可走
int maze[ROW][COL] = {{0, 1, 0, 0, 0},{0, 1, 0, 1, 0},{0, 0, 0, 0, 0},{0, 1, 1, 1, 0},{0, 0, 0, 1, 0}
};// 访问标记
int visited[ROW][COL] = {0};// 移动方向(上下左右)
int moveX[4] = {0, 0, -1, 1};
int moveY[4] = {-1, 1, 0, 0};// 检查当前位置是否合法
bool isValid(int x, int y) {if (x < 0 || x >= ROW || y < 0 || y >= COL) return false;if (maze[x][y] == 1 || visited[x][y] == 1) return false;return true;
}// DFS搜索迷宫路径
bool dfs(int x, int y) {// 如果达到右下角出口if (x == ROW - 1 && y == COL - 1) {visited[x][y] = 1;return true;}// 检查当前位置是否可走if (isValid(x, y)) {visited[x][y] = 1;  // 标记为已访问// 尝试每一个方向for (int i = 0; i < 4; i++) {int nextX = x + moveX[i];int nextY = y + moveY[i];if (dfs(nextX, nextY)) return true;}visited[x][y] = 0;  // 回溯,标记为未访问}return false;
}void printPath() {for (int i = 0; i < ROW; i++) {for (int j = 0; j < COL; j++) {printf("%d ", visited[i][j]);}printf("\n");}
}int main() {if (dfs(0, 0)) {printf("找到了通往出口的路径:\n");printPath();} else {printf("没有找到通往出口的路径.\n");}return 0;
}

说明

上述代码定义了一个5x5的迷宫和一个相应的访问数组。DFS函数尝试从入口(0,0)开始探索,使用一个递归方法来尝试所有可能的路径。如果找到一条到达出口(ROW-1, COL-1)的路径,该函数将返回true,并通过visited数组标记路径。

此代码还包括一个printPath函数,用于打印出到达终点的路径。这个解决方案可以直接应用于任何通过二维网格模拟的迷宫探索问题,非常适合需要路径查找的

4.C 语言实现 BFS 解迷宫

在生活中应用图搜索算法的一个常见场景是地图导航系统,如何在城市道路网中找到两点之间的最短路径。在这个实例中,我们将使用广度优先搜索(BFS)来模拟在城市的道路网络中寻找从一个地点到另一个地点的最短路径的情况。

在C语言中实现这样的模型,我们首先需要设置一个城市的道路网络图,然后使用 BFS 算法来找出两点之间的最短路径。

定义城市地图道路网络

我们首先定义一个图结构来表示城市中的路口(节点)和道路(边),然后实现 BFS 搜索找到最短路径。

C 语言代码示例

#include <stdio.h>
#include <stdlib.h>
#include <limits.h>typedef struct node {int vertex;struct node* next;
} Node;typedef struct {int numVertices;Node** adjLists;int* visited;int* distance;  // 用于存储起点到每个顶点的距离
} Graph;Node* createNode(int v) {Node* newNode = (Node*)malloc(sizeof(Node));newNode->vertex = v;newNode->next = NULL;return newNode;
}Graph* createGraph(int vertices) {Graph* graph = (Graph*)malloc(sizeof(Graph));graph->numVertices = vertices;graph->adjLists = (Node**)malloc(vertices * sizeof(Node*));graph->visited = (int*)malloc(vertices * sizeof(int));graph->distance = (int*)malloc(vertices * sizeof(int));for (int i = 0; i < vertices; i++) {graph->adjLists[i] = NULL;graph->visited[i] = 0;graph->distance[i] = INT_MAX;}return graph;
}void addEdge(Graph* graph, int src, int dest) {Node* newNode = createNode(dest);newNode->next = graph->adjLists[src];graph->adjLists[src] = newNode;newNode = createNode(src);newNode->next = graph->adjLists[dest];graph->adjLists[dest] = newNode;
}void BFS(Graph* graph, int startVertex) {int queue[1000], front = 0, rear = -1;graph->visited[startVertex] = 1;graph->distance[startVertex] = 0;queue[++rear] = startVertex;while (front <= rear) {int currentVertex = queue[front++];Node* temp = graph->adjLists[currentVertex];while (temp) {int adjVertex = temp->vertex;if (graph->visited[adjVertex] == 0) {graph->visited[adjVertex] = 1;graph->distance[adjVertex] = graph->distance[currentVertex] + 1; // 计算距离queue[++rear] = adjVertex;}temp = temp->next;}}
}int main() {Graph* graph = createGraph(8); // 假设城市有8个重要交叉路口addEdge(graph, 0, 1);addEdge(graph, 0, 3);addEdge(graph, 1, 2);addEdge(graph, 1, 4);addEdge(graph, 2, 5);addEdge(graph, 3, 4);addEdge(graph, 4, 5);addEdge(graph, 5, 6);addEdge(graph, 6, 7);BFS(graph, 0);  // 从路口0开始搜索printf("从0到7的最短路径是%d步.\n", graph->distance[7]);return 0;
}

说明

在上面的代码中,我们构建了一个模拟的城市道路网络,并通过广度优先搜索算法找到从节点 0 到节点 7 的最短路径。每个节点代表一个路口,每条边代表两个路口之间的直接道路。distance 数组用于存储从起始点到图中每个其他顶点的最短路径长度。

这种类型的实现在现实世界的导航

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/pingmian/4277.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Linux异步io机制 io_uring

io_uring作为2019年的后起之秀&#xff0c;为linux异步网络编程新增一把倚天大剑&#xff0c;让我们简单学习一下&#xff01; 数据结构&#xff1a; a. sq (submition queue)&#xff1a;提交队列&#xff0c;一个存放待执行事件的环形队列 b. cq (completion queue): 完成…

Node.js -- 包管理工具

文章目录 1. 概念介绍2. npm2.1 npm 下载2.2 npm 初始化包2.3 npm 包(1) npm 搜索包(2) npm 下载安装包(3) require 导入npm 包的基本流程 2.4 开发依赖和生产依赖2.5 npm 全局安装(1) 修改windows 执行策略(2) 环境变量Path 2.6 安装包依赖2.7 安装指定版本的包2.8 删除依赖2.…

【AI学习】Ben Thompson对 Nat Friedman 和 Daniel Gross的采访

读了Ben Thompson对 Nat Friedman 和 Daniel Gross的采访这篇文章&#xff0c;挺有趣。 先说最有趣的几个地方&#xff1a; 关于维苏威火山碳化古卷挑战&#xff1a;有趣而有意义&#xff01;有关日本的预测&#xff1a;有可能依靠芯片制造业&#xff0c;也许 2030 年代就又是…

visual studio2022,开发CMake项目添加rabbitmq库,连接到远程计算机并进行开发于调试

1.打开visual studio installer 。安装“用于 Windows 的 C CMake 工具” 2.新建CMake项目 3.点击VS的“工具”—>"选项“—>“跨平台”—>”连接管理器“,添加远程计算机。用来将VS编辑的代码传到服务器进行编译–连接—运行&#xff08;调试&#xff09;。 …

java中的泛型(三)——通配符

在前面的文章中我们简要介绍了泛型的概念以及泛型类和泛型方法的使用。在介绍泛型时我们说过在在java中一般用E、T、K、V、N、?这几个字母和符号来表示泛型&#xff0c;对于前面的几个字符它们的使用没有区别&#xff0c;只要注意它们所代表的类型就好。而对于最后一个&#x…

优化大型语言模型交互:提升查询和提示效果的26条原则

推荐下arxiv挂的一个提示词教程&#xff1a; https://github.com/VILA-Lab/ATLAS https://arxiv.org/abs/2312.16171 它提出了一套26条指导原则&#xff0c;改善和优化与大型语言模型&#xff08;LLMs&#xff09;的交互过程。通过这些原则&#xff0c;旨在简化对LLMs的查询和…

E4980A是德科技E4980A精密LCR表

181/2461/8938产品概述&#xff1a; Keysight E4980A 精密 LCR 表为各种元件测量提供了精度、速度和多功能性的最佳组合。E4980A 在低阻抗和高阻抗范围内提供快速测量速度和出色的性能&#xff0c;是元件和材料的一般研发和制造测试的终极工具。LAN、USB 和 GPIB PC 连接可提高…

概率论知识点(2)指数分布随机变量PDF,CDF及其特征函数

(1) X ∼ exp ⁡ ( 1 ) X\sim \exp(1) X∼exp(1), Y ∼ exp ⁡ ( 1 ) Y\sim \exp(1) Y∼exp(1), PDF: f X ( x ) = e − x , x > 0 f_{X}(x)=e^{-x},x>0 fX​(x)=e−x,x>0; f Y ( y ) = e − y , y > 0 f_{Y}(y)=e^{-y},y>0 fY​(y)=e−y,y>0CDF: F X…

【氮化镓】p-GaN HEMTs空穴陷阱低温冻结效应

这篇文章是关于低温条件下p-GaN高电子迁移率晶体管&#xff08;HEMTs&#xff09;栅极漏电的研究。文章通过电容深能级瞬态谱&#xff08;C-DLTS&#xff09;测试和理论模型分析&#xff0c;探讨了空穴陷阱对栅极漏电电流的影响。以下是对文章的总结&#xff1a; 摘要&#xf…

sql server 数据库的学习

前言&#xff1a; SQL Server是由微软公司开发的一种关系型数据库管理系统&#xff08;RDBMS&#xff09;&#xff0c;用于存储和检索数据。它提供了一个可扩展的、安全的和可靠的数据存储和管理解决方案&#xff0c;并主要用于构建企业级应用程序。SQL Server支持使用SQL&…

java中的异常处理机制

通俗易懂地说,java中的异常处理机制就是try-catch-finally, try是可能出现的异常,而catch是处理那些异常,可以有多个,catch中也可以用throw抛出异常,finally是无论如何都要进行执行的代码 catch中那个东西,只有一个异常处理了,才会执行下一个异常 接下来说说throw和throws吧 其…

本地认证的密码去哪了?怎么保证安全的?

1. windows登录的明文密码&#xff0c;存储过程是怎么样的&#xff1f;密文存在哪个文件下?该文件是否可以打开&#xff0c;并且查看到密文&#xff1f; 系统将输入的明文密码通过hash算法转为哈希值&#xff0c;且输入的值会在内存中立即删除无法查看。 然后将密文存放在C:…

基于Spring Boot的火车订票管理系统设计与实现

基于Spring Boot的火车订票管理系统设计与实现 开发语言&#xff1a;Java框架&#xff1a;springbootJDK版本&#xff1a;JDK1.8数据库工具&#xff1a;Navicat11开发软件&#xff1a;eclipse/myeclipse/idea 系统部分展示 前台首页功能界面图&#xff0c;在系统首页可以查看…

ROS机器人小车建模仿真与SLAM(5)

目录 一、ROS中使用摄像头 1.1 验证摄像头设备可用 1.2 安装cheese 1.3 测试 二、获取摄像头驱动包 2.1 usb_cam 2.1.1 rosrun方式运行 2.1.2 roslaunch方式运行 三、摄像头标定(camera calibration) 3.2 标定前准备 3.2.1 标定板 3.2.2 摄像头调焦 3.3 标定摄像头…

MySQL__索引

文章目录 &#x1f60a; 作者&#xff1a;Lion J &#x1f496; 主页&#xff1a; https://blog.csdn.net/weixin_69252724 &#x1f389; 主题&#xff1a; MySQL__索引&#xff09; ⏱️ 创作时间&#xff1a;2024年04月23日 ———————————————— 这里写目…

avl excite python二次开发1--python解释器需用内置解释器aws_cmd

avl excite python二次开发1--python解释器需用内置解释器aws_cmd 1、python解释器问题1.1、用外置python解释器&#xff0c;import WSInterface会失败(WSInterface.pyd)1.2、用内置解释器aws_cmd运行py脚本1.3 用内置解释器aws_python执行脚本三级目录 1、python解释器问题 1…

Python_AI库 Pandas的数据结构及基本操作

Python_AI库 Pandas的数据结构及基本操作 本文默认读者具备以下技能&#xff1a; 熟悉python基础知识&#xff0c;vscode或其它编辑工具 熟悉表格文件的基本操作 具备自主扩展学习能力 本文篇幅较长&#xff0c;但比较重要&#xff0c;希望读者可以认真看完并实例运行。 Pa…

Hugging Face 新开源Parler-TTS,高质量文本转语音模型,可自主训练定制声音,训练代码、模型、数据集全部公开

前言 Parler-TTS 是大名鼎鼎的huggingface推出的一款轻量级文本到语音&#xff08;TTS&#xff09;模型&#xff0c;它能够生成高质量、自然流畅的语音&#xff0c;并且能够模仿特定说话者的风格&#xff0c;包括性别、音高、说话风格等。这款模型是由Dan Lyth和Simon King创建…

【机器学习原理】决策树从原理到实践

基于树的模型是机器学习中非常重要的一类模型&#xff0c;最基础的就是决策树&#xff0c;本篇主要讲述决策树的原理和几类最常见的决策树算法&#xff0c;这也是更复杂的树模型算法的基础。 参考文章&#xff1a; 1.CSDN-基于熵的两个模型(ID3,C4.5)比较详细&#xff0c;有数字…

PotatoPie 4.0 实验教程(22) —— FPGA实现摄像头图像对数(log)变换

什么是图像的log变换&#xff1f; 总的来说&#xff0c;对数变换是一种常用的图像增强技术&#xff0c;可以改善图像的视觉质量、减少噪声以及突出图像中的细节&#xff0c;从而提高图像在视觉感知和分析中的效果和可用性。 图像的对数变换&#xff08;log transformation&am…