算法与数据结构:从基础到深入
1. 数组 (Array)
定义
- 一组连续内存空间存储的相同类型元素的集合。
- 特点:通过下标(索引)快速访问元素,但大小固定(静态数组)或可扩展(动态数组)。
核心操作
| 操作 | 时间复杂度 | 说明 |
|---|---|---|
| 访问元素 | O(1) | 通过索引直接访问(如arr[3]) |
| 插入元素 | O(n) | 需要移动后续元素 |
| 删除元素 | O(n) | 同上 |
| 查找元素 | O(n) | 遍历查找(无序数组) |
代码示例
# 创建数组
arr = [1, 2, 3, 4]# 访问元素
print(arr[0]) # 输出 1# 插入元素(在末尾添加)
arr.append(5) # O(1)(动态数组均摊时间)
arr.insert(2, 10) # O(n)(插入到中间)# 删除元素
arr.pop() # 删除末尾元素 O(1)
arr.pop(0) # 删除第一个元素 O(n)
应用场景
- 需要快速随机访问(如矩阵运算)
- 数据量已知或变化较小的场景
2. 链表 (Linked List)
定义
- 由节点组成的数据结构,每个节点包含数据和指向下一个节点的指针。
- 特点:内存非连续,插入/删除高效,但访问元素需要遍历。
类型
- 单链表:每个节点指向下一个节点。
- 双链表:节点同时指向前驱和后继。
- 循环链表:尾节点指向头节点。
核心操作
| 操作 | 时间复杂度 | 说明 |
|---|---|---|
| 访问元素 | O(n) | 从头节点开始遍历 |
| 插入/删除 | O(1) | 已知前驱节点时(如双链表) |
| 查找元素 | O(n) | 必须遍历 |
代码示例(单链表)
class ListNode:def __init__(self, val=0, next=None):self.val = valself.next = next# 创建链表:1 -> 2 -> 3
head = ListNode(1)
head.next = ListNode(2)
head.next.next = ListNode(3)# 插入节点(在节点2后插入4)
node = head.next
new_node = ListNode(4)
new_node.next = node.next
node.next = new_node # 链表变为1 -> 2 -> 4 -> 3# 删除节点(删除节点4)
node.next = node.next.next # 链表恢复为1 -> 2 -> 3
应用场景
- 频繁插入/删除的场景(如LRU缓存)
- 实现栈、队列等数据结构
3. 栈 (Stack)
定义
- 后进先出(LIFO)的线性结构。
- 核心操作:
push(入栈)、pop(出栈)、peek(查看栈顶)。
代码示例
# 用列表模拟栈
stack = []
stack.append(1) # push 1
stack.append(2) # push 2
top = stack[-1] # peek -> 2
stack.pop() # pop -> 2
应用场景
- 函数调用栈
- 括号匹配、表达式求值(如逆波兰表达式)
4. 队列 (Queue)
定义
- 先进先出(FIFO)的线性结构。
- 核心操作:
enqueue(入队)、dequeue(出队)。
代码示例
from collections import deque
queue = deque()
queue.append(1) # 入队
queue.append(2)
front = queue[0] # 查看队首
queue.popleft() # 出队 -> 1
变种队列
- 双端队列 (Deque):两端均可插入/删除。
- 优先队列 (Priority Queue):按优先级出队(通常用堆实现)。
应用场景
- 任务调度、消息队列
- BFS(广度优先搜索)
5. 哈希表 (Hash Table)
5.1 哈希表 概念
定义
- 通过键(Key)直接访问值(Value)的数据结构。
- 核心思想:哈希函数将键映射到存储位置。
冲突解决
- 开放寻址法:冲突时寻找下一个空槽。
- 链地址法:每个槽存储链表(如Python的字典)。
代码示例
# Python字典 即哈希表实现
hash_map = {}
hash_map["apple"] = 1 # 插入
hash_map["banana"] = 2
print(hash_map.get("apple")) # 获取 -> 1
del hash_map["banana"] # 删除
应用场景
- 快速查找(如数据库索引)
- 统计频率(如字母异位词分组)
5.2 链地址法(Chaining)
核心思想
- 每个数组的索引位置(称为“桶”)不再直接存储单个键值对,而是存储一个链表(或红黑树等其他数据结构)。
- 当多个键的哈希值冲突时,它们会被添加到同一个桶的链表中。
具体操作
- 插入键值对:
- 计算键的哈希值,找到对应桶。
- 如果桶为空,直接存入链表头节点。
- 如果桶不为空,遍历链表:
- 如果发现键已存在,更新值。
- 如果不存在,将新键值对添加到链表末尾(或头部)。
- 查找键值对:
- 计算键的哈希值,找到对应桶。
- 遍历链表,逐个比较键是否匹配。
代码示例(Python简化版)
class HashTable:def __init__(self, size=10):self.size = sizeself.table = [[] for _ in range(size)] # 每个桶是一个列表(模拟链表)def _hash(self, key):return hash(key) % self.size # 哈希函数def put(self, key, value):bucket_idx = self._hash(key)bucket = self.table[bucket_idx]# 遍历链表,检查是否已存在该键for i, (k, v) in enumerate(bucket):if k == key:bucket[i] = (key, value) # 更新键值对returnbucket.append((key, value)) # 添加新键值对def get(self, key):bucket_idx = self._hash(key)bucket = self.table[bucket_idx]for k, v in bucket:if k == key:return vreturn None # 未找到
为什么链地址法不会导致效率低下?
虽然链表需要遍历,但哈希表的设计目标是通过以下两点保证高效性:
(1) 哈希函数的均匀性
- 好的哈希函数会将键均匀分布到各个桶中,避免大量冲突。
- 例如,Python的哈希函数对字符串、整数等类型有优化,冲突概率极低。
(2) 负载因子(Load Factor)控制
- 负载因子 = 哈希表中元素数量 / 桶的数量。
- 当负载因子超过阈值(如0.75),哈希表会触发扩容(Rehashing):
- 创建一个更大的桶数组(例如翻倍)。
- 将所有键值对重新哈希到新桶中。
- 扩容后,冲突概率显著降低,链表长度保持较短(通常为0-2个节点)。
现代哈希表(如Java的HashMap)会进一步优化链地址法:
- 链表转红黑树(Java):当链表长度超过阈值(如8),将链表转换为红黑树,将查找时间从
O(n)优化为O(log n)。 - 动态扩容策略:根据负载因子智能调整桶的数量,平衡时间和空间。
5.3 开放地址法(Open Addressing)
核心思想
开放地址法的思想是,当发生冲突时,寻找另一个空的数组位置来存储冲突的元素。常见的解决方法有线性探测法、二次探测法和双重哈希法等。
具体实现
- 插入:当插入新元素时,计算哈希值,如果该位置已经被占用,就按照预定的探测策略(如线性探测)尝试查找下一个空的位置。
- 查找:查找时,先计算哈希值,如果当前位置的元素就是我们要查找的键,就直接返回值。如果当前位置不匹配,就根据探测策略继续查找其他位置,直到找到目标或确认该键不存在。
代码示例(Python简化版)
class HashTable:def __init__(self, size=10):self.size = sizeself.table = [None] * self.size # 每个桶直接存储键值对或标记def _hash(self, key):return hash(key) % self.sizedef _probe(self, start_idx):"""线性探测下一个可用位置"""idx = start_idxwhile True:if self.table[idx] is None or self.table[idx] == "DELETED":return idxidx = (idx + 1) % self.size # 回绕到数组开头if idx == start_idx: # 整个表已满raise Exception("Hash table is full")def put(self, key, value):start_idx = self._hash(key)idx = start_idx# 查找可插入的位置或更新现有键while True:if self.table[idx] is None or self.table[idx] == "DELETED":# 插入新键值对self.table[idx] = (key, value)returnelif self.table[idx][0] == key:# 键已存在,更新值self.table[idx] = (key, value)returnidx = (idx + 1) % self.size # 通过取余方式能够遍历整个数组if idx == start_idx:raise Exception("Hash table is full")def get(self, key):start_idx = self._hash(key)idx = start_idxwhile True:entry = self.table[idx]if entry is None:return None # 未找到elif entry != "DELETED" and entry[0] == key:return entry[1] # 返回找到的值idx = (idx + 1) % self.sizeif idx == start_idx:return None # 遍历完整个表未找到
6. 二叉树 (Binary Tree)
定义
- 每个节点最多有两个子节点(左子节点、右子节点)。
- 特殊类型:
- 二叉搜索树 (BST):左子树所有节点 < 根节点 < 右子树所有节点。
- 平衡二叉树(如AVL树、红黑树):通过旋转保持高度平衡。
遍历方式
| 遍历方式 | 顺序 |
|---|---|
| 前序遍历 | 根 -> 左 -> 右 |
| 中序遍历 | 左 -> 根 -> 右 |
| 后序遍历 | 左 -> 右 -> 根 |
| 层序遍历 | 按层级从上到下、从左到右 |
代码示例(二叉树节点)
class TreeNode:def __init__(self, val=0, left=None, right=None):self.val = valself.left = leftself.right = right# 创建二叉树
root = TreeNode(1)
root.left = TreeNode(2)
root.right = TreeNode(3)
应用场景
- 文件系统结构
- 表达式树(用于计算)
7. 堆 (Heap)
定义
- 一种完全二叉树,满足:
- 最大堆:父节点值 ≥ 子节点值。
- 最小堆:父节点值 ≤ 子节点值。
:::tip
完全二叉树是指除了最后一层外,其他层的节点都是 满的,并且最后一层的节点 尽可能靠左排列。
:::
核心操作
| 操作 | 时间复杂度 | 说明 |
|---|---|---|
| 插入元素 | O(log n) | 上浮调整(sift up) |
| 删除堆顶 | O(log n) | 下沉调整(sift down) |
代码示例(Python的 heapq 模块)
import heapq# 最小堆
heap = []
heapq.heappush(heap, 3)
heapq.heappush(heap, 1)
heapq.heappush(heap, 2)
print(heapq.heappop(heap)) # 输出1
应用场景
- 优先队列
- Top K问题(如最大的K个元素)
8. 图 (Graph)
定义
- 由 顶点(Vertex) 和 边(Edge) 组成的非线性结构。
- 表示方式:
- 邻接矩阵:二维数组表示顶点连接关系。
- 邻接表:为每个顶点维护一个链表,记录其邻居。
常见算法
- 遍历:DFS(深度优先)、BFS(广度优先)
- 最短路径:Dijkstra(无负权边)、Bellman-Ford(含负权边)
- 最小生成树:Prim算法、Kruskal算法
代码示例(邻接表表示图)
# 使用字典表示邻接表
graph = {'A': ['B', 'C'],'B': ['D'],'C': ['E'],'D': [],'E': []
}# DFS遍历
def dfs(graph, node, visited):if node not in visited:print(node)visited.add(node)for neighbor in graph[node]:dfs(graph, neighbor, visited)dfs(graph, 'A', set()) # 输出A -> B -> D -> C -> E
应用场景
- 社交网络(顶点为用户,边为好友关系)
- 路径规划(如地图导航)
相关文章:
算法与数据结构:从基础到深入
1. 数组 (Array) 定义 一组连续内存空间存储的相同类型元素的集合。特点:通过下标(索引)快速访问元素,但大小固定(静态数组)或可扩展(动态数组)。 核心操作 操作时间复杂度说明访…...
基于千兆5G网关的5G急救车方案
伴随5G网络的全面建成,5G技术的低延时、高速率、广接入等优势,为各行各业都带来了新一轮技术升级。在医疗救援方面,救护车是链接病患与医院的重要纽带,得益于5G物联网的融合应用,救护车也快速向联网化、信息化、智能化…...
【C#】的WPF或是WinForm实现Ctrl+ 的快捷键组合使用
在C#中,无论是WPF还是WinForms应用程序,处理快捷键(例如 Ctrl )通常涉及检测键盘输入并执行相应的命令或方法。 WPF 实现 在WPF中,可以通过设置一个控件的 InputBindings 属性来绑定快捷键。 <Window x:Class&qu…...
c语言样式主题 清爽风格 代码色彩 keil风格 适合单片机开发GD32 STM32等 cursor或者vscode 的settings.json文件
c语言样式主题 清爽风格 代码色彩 keil风格 适合单片机开发GD32 STM32等 cursor或者vscode 的settings.json文件 如上图,是不是和keil mdk很相近。 代码色彩,简单,配合 // 设置工作台主题为 Visual Studio 2017 Light - C 主题使用…...
DeepSeek API 调用 - Spring Boot 实现
DeepSeek API 调用 - Spring Boot 实现 1. 项目依赖 在 pom.xml 中添加以下依赖: <dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-webflux</artifactId></depe…...
图数据库Neo4j面试内容整理-节点(Node)
在图数据库中,节点(Node)是图结构中的基本构建块,代表实体或对象。节点通常用于存储数据模型中的主要对象,比如人、商品、地点等。在图数据库中,节点是通过标签(Label)来分类的,并且可以包含属性(Property)来描述它们的详细信息。 1. 节点的组成<...
使用verilog 实现 cordic 算法 ----- 旋转模式
1-设计流程 ● 了解cordic 算法原理,公式,模式,伸缩因子,旋转方向等,推荐以下链接视频了解 cordic 算法。哔哩哔哩-cordic算法原理讲解 ● 用matlab 或者 c 实现一遍算法 ● 在FPGA中用 verilog 实现,注意…...
2.14寒假
这几天复习的搜索把之前做过的题目看了一下。 解析:int dx[5]{0,0,1,0,-1}; 和 int dy[5]{0,1,0,-1,0};:这两个数组用于表示上下左右四个方向的偏移量,方便在 DFS 中访问相邻的元素。o 和 p 分别表示当前搜索位置的行和列。边界条件判断&…...
基于逻辑概率的语义信道容量(Semantic Channel Capacity)和语义压缩理论(Semantic Compression Theory)
基于逻辑概率的语义信道容量(Semantic Channel Capacity)和语义压缩理论(Semantic Compression Theory)是语义通信(Semantic Communication, SemCom)的核心研究方向,它们旨在优化通信效率&#…...
DeepSeek R1本地部署教程
尽管许多卖课博主声称能轻松运行满血版DeepSeek R1,但满血版R1模型参数高达671B,仅模型文件就需要404GB存储空间,运行时更需要约1300GB显存。 对于没有卡的普通玩家来说,运行的条件苛刻,且门槛极高。基于此࿰…...
CEF132编译指南 MacOS 篇 - 获取 CEF 源码 (五)
1. 引言 在完成了所有必要工具的安装和配置之后,我们正式进入获取 CEF132 源码的阶段。对于 macOS 平台,CEF 的源码获取过程需要特别注意不同芯片架构(Intel 和 Apple Silicon)的区别以及版本管理。本篇将作为 CEF132 编译指南系…...
TypeScript装饰器 ------- 学习笔记分享
目录 一. 简介 二. 类装饰器 1. 基本语法 2. 应用举例 3. 关于返回值 4. 关于构造类型 5. 替换被装饰的类 三. 装饰器工厂 四. 装饰器组合 五. 属性装饰器 1. 基本语法 2. 关于属性遮蔽 3. 应用举例 六. 方法装饰器 1. 基本语法 2. 应用举例 七. 访问器装饰器 …...
FPGA实现UltraScale GTH光口视频转USB3.0传输,基于FT601+Aurora 8b/10b编解码架构,提供2套工程源码和技术支持
目录 1、前言工程概述免责声明 2、相关方案推荐我已有的所有工程源码总目录----方便你快速找到自己喜欢的项目我这里已有的 GT 高速接口解决方案本博已有的FPGA驱动USB通信方案 3、工程详细设计方案工程设计原理框图输入Sensor之-->OV5640摄像头动态彩条输入视频之-->ADV…...
蓝桥杯篇---实时时钟 DS1302
文章目录 前言特点简介1.低功耗2.时钟/日历功能3.32字节的额外RAM4.串行接口 DS1302 引脚说明1.VCC12.VCC23.GND4.CE5.I/O6.SCLK DS1302 寄存器1.秒寄存器2.分钟寄存器3.小时寄存器4.日寄存器5.月寄存器6.星期寄存器7.年寄存器8.控制寄存器 DS1302 与 IAP25F2K61S2 的连接1.CE连…...
C语言蓝桥杯1003: [编程入门]密码破译
要将"China"译成密码,译码规律是:用原来字母后面的第4个字母代替原来的字母. 例如,字母"A"后面第4个字母是"E"."E"代替"A"。因此,"China"应译…...
【MySQL在Centos 7环境安装】
文章目录 一. 卸载不必要的环境二. 检查系统安装包三. 卸载这些默认安装包四. 获取mysql官⽅yum源五. 安装mysql yum 源,对⽐前后yum源六. 看看能不能正常⼯作七. 安装mysql服务八. .查看配置⽂件和数据存储位置九. 启动服务并查看服务是否存在十. 登陆⽅法十一. 设…...
科技引领未来,中建海龙C-MiC 2.0技术树立模块化建筑新标杆
在建筑行业追求高效与品质的征程中,中建海龙科技有限公司(简称“中建海龙”)以其卓越的创新能力和强大的技术实力,不断书写着装配式建筑领域的新篇章。1 月 10 日,由深圳安居集团规划,中建海龙与中海建筑共…...
玩转观察者模式
文章目录 什么是观察者模式解决方案结构适用场景实现方式观察者模式优缺点优点:缺点:什么是观察者模式 观察者模式通俗点解释就是你在观察别人,别人有什么变化,你就做出什么调整。观察者模式是一种行为设计模式,允许你定义一种订阅机制,可在对象事件发生时通知多个“观察…...
Baklib知识中台构建企业智能运营核心架构
内容概要 在数字化转型的浪潮中,企业对于知识的系统化管理需求日益迫切。Baklib作为新一代的知识中台,通过构建智能运营核心架构,为企业提供了一套从知识汇聚到场景化落地的完整解决方案。其核心价值在于将分散的知识资源整合为统一的资产池…...
Anaconda +Jupyter Notebook安装(2025最新版)
Anaconda安装(2025最新版) Anaconda简介安装1:下载anaconda安装包2: 安装anaconda3:配置环境变量4:检查是否安装成功5:更改镜像源6:更新包7:检查 Jupyter Notebook一.Jup…...
手游刚开服就被攻击怎么办?如何防御DDoS?
开服初期是手游最脆弱的阶段,极易成为DDoS攻击的目标。一旦遭遇攻击,可能导致服务器瘫痪、玩家流失,甚至造成巨大经济损失。本文为开发者提供一套简洁有效的应急与防御方案,帮助快速应对并构建长期防护体系。 一、遭遇攻击的紧急应…...
stm32G473的flash模式是单bank还是双bank?
今天突然有人stm32G473的flash模式是单bank还是双bank?由于时间太久,我真忘记了。搜搜发现,还真有人和我一样。见下面的链接:https://shequ.stmicroelectronics.cn/forum.php?modviewthread&tid644563 根据STM32G4系列参考手…...
【2025年】解决Burpsuite抓不到https包的问题
环境:windows11 burpsuite:2025.5 在抓取https网站时,burpsuite抓取不到https数据包,只显示: 解决该问题只需如下三个步骤: 1、浏览器中访问 http://burp 2、下载 CA certificate 证书 3、在设置--隐私与安全--…...
NLP学习路线图(二十三):长短期记忆网络(LSTM)
在自然语言处理(NLP)领域,我们时刻面临着处理序列数据的核心挑战。无论是理解句子的结构、分析文本的情感,还是实现语言的翻译,都需要模型能够捕捉词语之间依时序产生的复杂依赖关系。传统的神经网络结构在处理这种序列依赖时显得力不从心,而循环神经网络(RNN) 曾被视为…...
C++.OpenGL (14/64)多光源(Multiple Lights)
多光源(Multiple Lights) 多光源渲染技术概览 #mermaid-svg-3L5e5gGn76TNh7Lq {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-3L5e5gGn76TNh7Lq .error-icon{fill:#552222;}#mermaid-svg-3L5e5gGn76TNh7Lq .erro…...
七、数据库的完整性
七、数据库的完整性 主要内容 7.1 数据库的完整性概述 7.2 实体完整性 7.3 参照完整性 7.4 用户定义的完整性 7.5 触发器 7.6 SQL Server中数据库完整性的实现 7.7 小结 7.1 数据库的完整性概述 数据库完整性的含义 正确性 指数据的合法性 有效性 指数据是否属于所定…...
Go语言多线程问题
打印零与奇偶数(leetcode 1116) 方法1:使用互斥锁和条件变量 package mainimport ("fmt""sync" )type ZeroEvenOdd struct {n intzeroMutex sync.MutexevenMutex sync.MutexoddMutex sync.Mutexcurrent int…...
Redis:现代应用开发的高效内存数据存储利器
一、Redis的起源与发展 Redis最初由意大利程序员Salvatore Sanfilippo在2009年开发,其初衷是为了满足他自己的一个项目需求,即需要一个高性能的键值存储系统来解决传统数据库在高并发场景下的性能瓶颈。随着项目的开源,Redis凭借其简单易用、…...
第7篇:中间件全链路监控与 SQL 性能分析实践
7.1 章节导读 在构建数据库中间件的过程中,可观测性 和 性能分析 是保障系统稳定性与可维护性的核心能力。 特别是在复杂分布式场景中,必须做到: 🔍 追踪每一条 SQL 的生命周期(从入口到数据库执行)&#…...
c++第七天 继承与派生2
这一篇文章主要内容是 派生类构造函数与析构函数 在派生类中重写基类成员 以及多继承 第一部分:派生类构造函数与析构函数 当创建一个派生类对象时,基类成员是如何初始化的? 1.当派生类对象创建的时候,基类成员的初始化顺序 …...
