蓝桥杯备考——算法

一、排序

冒泡排序、选择排序、插入排序、 快速排序、归并排序、桶排序

 

二、枚举

三、二分查找与二分答案

四、搜索(DFS)

DFS(DFS基础、回溯、剪枝、记忆化)

1.DFS算法(深度优先搜索算法)

深度优先搜索( DFS )是一种用于遍历或搜索图或树的算法,它从起始节点开始,沿着一条路径一直深入直到无法继续为止,然后回溯到上一个节点继续探索。 DFS 使用来记录遍历的路径,它优先访问最近添加到栈的节点。

DFS 的主要优点是简单且易于实现,它不需要额外的数据结构来记录节点的访问情况,仅使用栈来存储遍历路径。然而, DFS 可能会陷入无限循环中,因为它不考虑节点是否已经访问过。

  对于一个连通图,深度优先搜索遍历的过程如下:

(1)从图中某个顶点v出发,访问v;

(2)找到刚访问过的顶点的第一个未被访问的邻接点,访问该顶点。 以该顶点为新顶点,重 复此步骤, 直至刚访问过的顶点没有未被访问的邻接点为止。

(3)返回前一个访问过的且仍有未被访问的邻接点的顶点,找出该顶点的下一个未被访问的邻接点, 访问该顶点。

(4)重复步骤 (2) 和(3), 直至图中所有顶点都被访问过,搜索结束。 

677c768ab5eb8b76c9f1c64d779c35b6.png

顶点访问序列:v1 -> v2 -> v4 -> v8 -> v5 -> v3 -> v6 -> v7

DFS 使用来记录遍历的路径,它优先访问最近添加到栈的节点。

 显然, 深度优先搜索遍历连通图是一个递归的过程。 为了在遍历过程中便千区分顶点是否已

 被访问,需附设访问标志数组 visited[n] , 其初值为 "false", 一旦某个顶点被访问,则其相应的分

量置为 "true"。  

python语言:

# 图的DFS遍历
def dfs(graph, start, visited):# 访问当前节点print(start, end=' ')# 标记当前节点为已访问visited[start] = True# 遍历当前节点的邻居节点for neighbor in graph[start]:# 如果邻居节点未被访问,则继续深度优先搜索if not visited[neighbor]:dfs(graph, neighbor, visited)# 图的邻接表表示
graph = {'1': ['2', '3'],'2': ['2', '4', '5'],'3': ['1', '6', '7'],'4': ['2','8'],'5': ['2','8'],'6': ['3','7'],'7': ['3','6'],'8': ['4','5']
}# 标记节点是否已访问的列表
visited = {node: False for node in graph}# 从节点A开始进行DFS遍历
print("DFS遍历结果:")
dfs(graph, '1', visited)

C++ / C语言:

算法1.深度优先搜索遍历连通图

// 1. 深度优先搜索遍历连通图
bool visited[MVNum];         // 访问标志数组,其初值设为“false”
void DFS(Graph G, int v)
{    // 从第v个顶点出发 递归地深度优先遍历图Gcout << v; visited[v] = true;for (w=FirstAdjVex(G,v); w>=0; w=NextAdjVex(G,v,w))// 依次检查v的所有邻接点w,FirstAdjVex(G,v)表示v的第一个邻接点// NextAdjVex(G,v,w)表示v相对于w的下一个邻接点,w>=0表示存在邻接点if (!visited[w])    DFS(G,w);      // 对v的尚未访问的邻接点w递归调用DFS
}

算法2.深度优先搜索遍历 非连通图

若是非连通图, 上述遍历过程执行之后, 图中一定还有顶点未被访间,需要从图中另选

一个未被访问的顶点作为起始点 , 重复上述深度优先搜索过程, 直到图中所有顶点均被访问

过为止。这样, 要实现对非连通图的遍历,需要循环调用算法 1, 具体实现如算法 2所示。

void DFSTraverse(Graph G) 
{ //对非连通图G做深度优先遍历for(v=O;v<G.vexnum;++v)    visited[v]=false;    // 访问标志数组初始化for(v=O;v<G.vexnum;++v)     // 循环调用算法1if(!visited[v])    DFS(G,v);     // 对尚未访问的顶点调用DFS
}

算法 3  采用 邻接矩阵 表示图的深度优先搜索遍历

void DFS_AM(AMGraph G,int v) 
{    // 图G为 邻接矩阵类型,从第v个顶点出发深度优先搜索遍历图Gcout<<v; visited[v]=true;     // 访问第v个顶点,并置访问标志数组相应分址值为truefor(w=O; w<G.vexnum; w++)     // 依次检查邻接矩阵 v所在的行if((G.arcs[v][w] !=O) && (!visited[w]))    DFS(G,w);  //G.arcs[v][w] ! =0表示w是v的邻接点, 如果w未访问, 则递归调用DFS
}

算法 4 采用邻接表表示图的深度优先搜索遍历

void DFS_AL (ALGraph G,int v) 
{    //图G为 邻接表 类型, 从第v个顶点出发深度优先搜索遍历图Gcout<<v; visited[v]=true;  // 访问第v个顶点,并置访问标志数组相应分量值为truep=G.vertices[v] .firstarc;   //p指向v的边链表的第一个边结点while(p!=NULL)     // 边结点非空{w=p->adjvex;           // 表示w是v的邻接点if(!visited[w])    DFS(G,w);    // 如果w未访问, 则递归调用DFSp=p->nextarc;         //p指向下一个边结点}
}

例题:1.最大连通

问题描述:(填空题)

小兰有一个30行60列的数字矩阵,矩阵中的每个数都是0或1。


110010000011111110101001001001101010111011011011101001111110010000000001010001101100000010010110001111100010101100011110 001011101000100011111111111010000010010101010111001000010100 101100001101011101101011011001000110111111010000000110110000 010101100100010000111000100111100110001110111101010011001011 010011011010011110111101111001001001010111110001101000100011 101001011000110100001101011000000110110110100100110111101011 101111000000101000111001100010110000100110001001000101011001 001110111010001011110000001111100001010101001110011010101110 001010101000110001011111001010111111100110000011011111101010 011111100011001110100101001011110011000101011000100111001011 011010001101011110011011111010111110010100101000110111010110 001110000111100100101110001011101010001100010111110111011011 111100001000001100010110101100111001001111100100110000001101 001110010000000111011110000011000010101000111000000110101101 100100011101011111001101001010011111110010111101000010000111 110010100110101100001101111101010011000110101100000110001010 110101101100001110000100010001001010100010110100100001000011 100100000100001101010101001101000101101000000101111110001010 101101011010101000111110110000110100000010011111111100110010 101111000100000100011000010001011111001010010001010110001010 001010001110101010000100010011101001010101101101010111100101 001111110000101100010111111100000100101010000001011101100001 101011110010000010010110000100001010011111100011011000110010 011110010100011101100101111101000001011100001011010001110011 000101000101000010010010110111000010101111001101100110011100 100011100110011111000110011001111100001110110111001001000111 111011000110001000110111011001011110010010010110101000011111 011110011110110110011011001011010000100100101010110000010011 010011110011100101010101111010001001001111101111101110011101

 如果从一个标为1的位置可以通过上下左右走到另一个标为1的位置,则称两个位置连通。与某一个标为1的位置连通的所有位置(包括自己)组成一个连通分块。

请问矩阵中最大的连通分块有多大?

答案:

import os
import sysdef dfs(x, y, num): # x,y是当前的位置,num是最大连通的数量vis[x][y] = 1   # 表明这个位置已经被搜素过了for dx,dy in [(1, 0), (-1, 0), (0,1), (0, -1)]:   # 标准的上下左右搜索current_x = x + dxcurrent_y = y + dyif 0 <= current_x < 30 and 0 <= current_y <60:  # 边界限制try:if vis[current_x][current_y] != 1 and data[current_x][current_y] == '1':  # 上下左右有位置没有被探索同时还是字符串的'1'num = dfs(current_x,current_y,num)except:   # 这里是方便找到如果输入错误是在哪,用来检查循环条件是否写错print(current_x)print(current_y)return num + 1    # 本身的1加上所有与它相连的numdata =[
"110010000011111110101001001001101010111011011011101001111110","010000000001010001101100000010010110001111100010101100011110","001011101000100011111111111010000010010101010111001000010100","101100001101011101101011011001000110111111010000000110110000","010101100100010000111000100111100110001110111101010011001011","010011011010011110111101111001001001010111110001101000100011","101001011000110100001101011000000110110110100100110111101011","101111000000101000111001100010110000100110001001000101011001","001110111010001011110000001111100001010101001110011010101110","001010101000110001011111001010111111100110000011011111101010","011111100011001110100101001011110011000101011000100111001011","011010001101011110011011111010111110010100101000110111010110","001110000111100100101110001011101010001100010111110111011011","111100001000001100010110101100111001001111100100110000001101","001110010000000111011110000011000010101000111000000110101101","100100011101011111001101001010011111110010111101000010000111","110010100110101100001101111101010011000110101100000110001010","110101101100001110000100010001001010100010110100100001000011","100100000100001101010101001101000101101000000101111110001010","101101011010101000111110110000110100000010011111111100110010","101111000100000100011000010001011111001010010001010110001010","001010001110101010000100010011101001010101101101010111100101","001111110000101100010111111100000100101010000001011101100001","101011110010000010010110000100001010011111100011011000110010","011110010100011101100101111101000001011100001011010001110011","000101000101000010010010110111000010101111001101100110011100","100011100110011111000110011001111100001110110111001001000111","111011000110001000110111011001011110010010010110101000011111","011110011110110110011011001011010000100100101010110000010011","010011110011100101010101111010001001001111101111101110011101"]
res = 0
vis = [[0 for i in range(60)] for j in range(30)]   # 标记数组
for i in range(30):  # i和j是位置for j in range(60):if data[i][j] == '1' and vis[i][j] == 0:num = 0num = dfs(i,j,num)res = max(num, res)
print(res)

例题2.

 

2. 广度优先搜索( BFS )算法

是一种用于遍历或搜索图或树的算法,它从起始节点开始,逐层地向外扩展,先访问当前节点的所有邻居节点,然后再访问邻居节点的邻居节点,直到遍历完所有节点。

BFS 使用队列来记录遍历的路径,它优先访问最早添加到队列的节点。 BFS 的主要优点是能够找到起始节点到目标节点的最短路径,因为它是逐层遍历的。

677c768ab5eb8b76c9f1c64d779c35b6.png

python语言

from collections import deque# 图的BFS遍历
def bfs(graph, start):# 使用队列来记录遍历路径queue = deque([start])# 标记节点是否已访问的集合visited = set([start])while queue:     # 当栈不为空node = queue.popleft()    # 左端出栈print(node, end=' ')for neighbor in graph[node]:if neighbor not in visited:queue.append(neighbor)    # 右端进栈visited.add(neighbor)# 图的邻接表表示
graph = {'1': ['2', '3'],'2': ['2', '4', '5'],'3': ['1', '6', '7'],'4': ['2','8'],'5': ['2','8'],'6': ['3','7'],'7': ['3','6'],'8': ['4','5']
}# 从节点A开始进行BFS遍历
print("BFS遍历结果:")
bfs(graph, '1')      # 1 2 3 4 5 6 7 8

python: collections模块——双向队列(deque)
类似于list的容器,可以快速的在队列头部和尾部添加、删除元素

 

3.  DFS 与 BFS 的对比

DFSBFS 是两种不同的图遍历算法,在不同的应用场景下具有不同的优势:

  • DFS 适用于找到起始节点到目标节点的路径,但不一定是最短路径。它通过递归的方式深入探索图的分支,因此对于深度较小的图或树, DFS 通常表现较好。
  • BFS 适用于找到起始节点到目标节点的最短路径。它通过逐层遍历图的节点,从而保证找到的路径是最短的。在需要寻找最短路径的情况下, BFS 是更好的选择

 

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

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

相关文章

Javascript垃圾回收机制-运行机制(大厂内部培训版本)

前言 计算机基本组成&#xff1a; 我们编写的软件首先读取到内存&#xff0c;用于提供给 CPU 进行运算处理。 内存的读取和释放&#xff0c;决定了程序性能。 冯诺依曼结构 解释和编译 这两个概念怎么理解呢。 编译相当于事先已经完成了可以直接用。好比去饭店吃饭点完上…

python面向对象基础入门

面向对象 基本的实现方法大概如此 class Student(object):def __init__(self, name, score):self.name nameself.score scoredef print_score(self):print(%s: %s % (self.name, self.score))在面向对象的思想中&#xff0c;面对一个问题&#xff0c;首先应该考虑这个问题所…

阿里云ACK容器如何配置pod分散在集群的不同节点上

阿里云ACK容器如何配置pod分散在集群的不同节点上 1.核心原理 是使用pod间反亲和性&#xff08;podAntiAffinity&#xff09;&#xff0c;pod间反亲和性又分为软约束反亲和和硬约束反亲和。 2.软约束反亲和和硬约束反亲和区别&#xff1a; preferredDuringSchedulingIgnore…

ffmpeg+D3D实现的MFC音视频播放器,支持录像、截图、音视频播放、码流信息显示等功能

一、简介 本播放器是在vs2019 x86下开发&#xff0c;通过ffmpeg实现拉流解码功能&#xff0c;通过D3D实现视频的渲染功能。截图功能采用libjpeg实现&#xff0c;可以截取jpg图片&#xff0c;图片的默认保存路径是在C:\MYRecPath中。录像功能采用封装好的类Mp4Record实现&#x…

怎样遵守编程规范,减少和控制C++编程中出现的bug?

遵守编程规范和最佳实践是减少和控制 C 编程中出现 bug 的重要手段。以下是一些具体的建议和策略&#xff0c;帮助你编写更健壮、更易于维护的 C 代码。 1. 遵循 C 标准和最佳实践 使用现代 C 特性&#xff1a;尽可能使用 C11 及之后的标准&#xff0c;避免使用过时的特性和库…

从零开始学习 sg200x 多核开发之 uboot 网络功能使能

sophpi u-boot 默认未开启网络功能&#xff0c;需要手动开启&#xff0c;为了在 u-boot 下可以通过 tftp 下载固件&#xff0c;先测试 u-boot 下网络功能。 u-boot 网络功能开启 在 build/boards/cv181x/sg2002_wevb_riscv64_sd/u-boot/cvitek_sg2002_wevb_riscv64_sd_defcon…

编译sddm 0.18.1 依赖

github 下载后cmake编译会出现一些依赖 Could not find a package configuration file provided by "ECM" 则执行 sudo apt install extra-cmake-modules PAM headers not found - configure: 解决方法 yum -y install pam-devel No package ‘xcb-xkb’ foun…

C++11标准模板(STL)- 常用数学函数 - 宏常量 - 求值得到float类型的安静NaN(NAN)

常用数学函数 求值得到float类型的安静NaN NAN 定义于头文件 <math.h> #define NAN /*implementation defined*/ (C99 起) 宏 NAN 展开成求值为安静非数&#xff08; QNaN &#xff09;的 float 类型常量表达式。若实现不支持 QNaN &#xff0c;则不定义此宏。 用于打…

NodeJS 百度智能云文本转语音(实测)

现在文本转语音的技术已经非常完善了&#xff0c;尽管网络上有许多免费的工具&#xff0c;还是测试了专业的服务&#xff0c;选择了百度的TTS服务。 于是&#xff0c;在百度智能云注册和开通了文本转语音的服务&#xff0c;尝试使用NodeJS 实现文本转语音服务。但是百度的文档实…

信也科技和云杉网络的AI可观测性实践分享

1. 信也科技 2、云杉网络 2.1 中国移动

SQLite 安装指南

SQLite 安装指南 SQLite 是一种轻量级的数据库管理系统,因其小巧、快速和易于使用而广受欢迎。本指南将详细介绍如何在不同的操作系统上安装 SQLite,并确保您能够顺利开始使用它。 1. Windows 系统上的安装 1.1 下载 SQLite 访问 SQLite 官方网站:sqlite.org/download.ht…

【项目开发】Web App vs Native App,开发者作何选择?

文章目录 引言市场需求与机会竞技场的右侧:为移动屏幕优化的 Web 应用移动 Web 应用的优缺点移动 Web 应用的优势移动版Web应用的缺点引言 在建立稳固的移动网络存在感并为用户提供流畅的移动体验时,移动网络应用的必要性已经不再是可选项。然而,随着移动原生应用的兴起,出…

解析煤矿一张图

解析煤矿一张图 ​ 煤矿一张图是指通过数字化、智能化技术将煤矿的各项信息、数据和资源进行集中展示和管理&#xff0c;形成一个综合的可视化平台。这一平台将矿井的地理信息、设备状态、人员位置、安全生产、环境监测等信息整合成一个统一的“图形”&#xff0c;以便于管理者…

管家婆工贸ERP BR039.采购订单关联MRP明细表

最低适用版本&#xff1a; 工贸系列 23.8 插件简要功能说明&#xff1a; 采购订单明细表&#xff0c;支持显示采购订单明细上游请购单明细关联的MRP中对应销售订单明细产成品相关信息更多细节描述见下方详细文档 插件操作视频&#xff1a; 进销存类定制插件--采购订单关联M…

SpringBootTest常见错误解决

1.启动类所在包错误 问题 由于启动类所在包与需要自动注入的类的包不在一个包下&#xff1a; 启动类所在包&#xff1a; com.exmaple.test_02 但是对于需要注入的类却不在com.exmaple.test_02下或者其子包下&#xff0c;就会导致启动类无法扫描到该类&#xff0c;从而无法对…

Java 全栈知识体系

包含: Java 基础, Java 部分源码, JVM, Spring, Spring Boot, Spring Cloud, 数据库原理, MySQL, ElasticSearch, MongoDB, Docker, k8s, CI&CD, Linux, DevOps, 分布式, 中间件, 开发工具, Git, IDE, 源码阅读&#xff0c;读书笔记, 开源项目...

高效管理生产线:哪些项目管理工具最适合制造企业?

制造业的生产管理往往涉及复杂的流程和多部门协作&#xff0c;如何确保各环节顺利对接、信息准确传递&#xff0c;是每一家制造企业都在不断优化的问题。面对这些管理难题&#xff0c;越来越多的制造企业引入了项目管理软件&#xff0c;通过直观的任务分配、进度跟踪、数据反馈…

微信小程序 https://thirdwx.qlogo.cn 不在以下 downloadFile 合法域名列表中

授权登录后&#xff0c;拿到用户头像进行加载&#xff0c;但报错提示&#xff1a; https://thirdwx.qlogo.cn 不在以下 downloadFile 合法域名列表中 解决方法一&#xff08;未完全解决&#xff0c;临时处理&#xff09;&#xff1a;在微信开发者工具将不校验...勾上就可以访问…

Android - Pixel 6a 手机OS 由 Android 15 降级到 Android 14 操作记录

Pixel 6a 手机由 Android 14 升级到 Android 15了&#xff0c;但是由于一些原因又想降级回 Android 14&#xff0c; 能降吗&#xff1f;该怎么降级呢&#xff1f;本篇文章来记述实际操作过程&#xff0c;希望能给想做相同操作的人一些帮助。 答案当然是能降&#xff0c;而且我…

SOL链上Meme生态的崛起与未来#Dapp开发#链游#交易所#公链搭建

近年来&#xff0c;随着区块链技术的普及和NFT文化的流行&#xff0c;meme&#xff08;网络迷因&#xff09;逐渐成为区块链生态中的重要组成部分。meme不仅是一种互联网文化符号&#xff0c;更逐步渗透进了去中心化金融&#xff08;DeFi&#xff09;、NFT和元宇宙等多个领域&a…