【算法与数据结构】数组
文章目录
- 前言
- 数组
- 数组的定义
- 数组的基本操作
- 增加元素
- 删除元素
- 修改元素
- 查找元素
- C++ STL 中的数组
- array
- vector
- Python3 中的列表
- 访问
- 更改元素值
- 遍历列表
- 检查列表中是否存在某元素
- 增加元素
- 删除元素
- 拷贝列表
- 总结 Python3 列表的常用操作
- 参考资料
- 写在最后
前言
本系列专注更新基本数据结构,现以更新:
【算法与数据结构】数组.
【算法与数据结构】哈希表.
数组
数组的定义
数组是一种在内存中有着一块连续的内存空间的,并且由相同类型的元素组成的线性数据结构。以整数数组为例,数组的存储方式如下图所示:
在上图中可以看出数组在计算机中就是内存中一块连续的存储单元。数据元素的内存地址表示的就是该元素存放在内容中的地址,因为整型数据占据四个字节大小的内存,所以相邻两个元素地址之间相差 4。
在上图所示的数组中,数据元素的个数为 7,并且数组中都是整型元素。数组中每一个元素都可以通过「下标索引」来获取。下标索引从 0 开始(在计算机中数数都是从 0 开始),到数据元素的个数减一。
之所以称数组是一种线性数据结构是因为数组中所有数据元素排成像一条线一样的结构,每个数据元素最多只有前、后两个方向。链表、栈、队列这几种数据结构也有这样的线性特征。
数组的基本操作
几乎所有的数据结构都会涉及到增、删、改、查四个基本操作,数组也不例外。
增加元素
增加元素之前需要先检查数组是否已经满了(达到最大容量),如果满了就需要重新在内存中找到一块连续的地方放置原来数组中的元素以及新加入的元素。如果使用的是 C++ 中的 vector 容器,就不用担心容量不够的问题,因为在数组容量不够时 vector 会自动扩容。通常在数组尾部增加元素的时间复杂度为 O ( 1 ) O(1) O(1)。
如果在数组 nums 中位置 i 处插入一个新的元素 val,通常有以下步骤:
- 先检查
i是否有效,即在数组的下标范围内; - 确认有效后,检查数组
i处是否已经存在元素了:- 没有元素当然好,直接更新
nums[i] = val; - 但是通常会有元素,这时候就需要将
i及之后位置的元素向后挪动一个位置,然后将val放在空出来的位置i处。
- 没有元素当然好,直接更新
- 这种插入情况最坏的时间复杂度为 O ( n ) O(n) O(n), n n n 是整个数组的长度。
这里就不考虑插入元素时数组满了的问题了,因为在 C++ 程序中通常都使用 vector 作为数组,这样一旦满了就会自动扩容。
删除元素
删除元素也分几种情况:
- 删除数组尾部元素,直接将数字计数值减一即可,这通常是 C 语言中的做法。前面已经说了 C++ 中几乎都用 vector 这个可动态扩容的数组,于是删除尾部元素直接
pop_back()。在 Python3 中直接pop()。 - 删除数组
nums中位置i的元素,通常有两个方法,当然在使用两个方法之前都要先检查i是否有效:- 借助临时数组:将原数组
nums中除了i位置表示的元素之外的所有元素复制到临时数组中,然后清空数组nums,最后再将临时数组中元素复制到nums中。这种方法需要遍历两次数组,渐进时间复杂度为 O ( n ) O(n) O(n),空间复杂度为 O ( n ) O(n) O(n)。 - 原地操作:利用
i位置后一位置的元素去覆盖i位置,即i+1位置的元素去覆盖i位置的元素,i+2位置的元素去覆盖i+1位置的元素,以此类推,直到i = n,最后再把最有一个元素删掉。时间复杂度为 O ( n ) O(n) O(n),空间复杂度为 O ( 1 ) O(1) O(1)。通常有关原地删除数组中元素的操作指的就是 覆盖。
- 借助临时数组:将原数组
- 最后一种情况就是「基于特定条件进行删除」,那就需要遍历数组,根据条件筛选出需要删除的元素或位置,一个个删除就好了。
通常删除操作的时间复杂度为 O ( n ) O(n) O(n)。
修改元素
这种操作就简单了。通过遍历数组找到需要修改的元素,直接修改即可。这种操作的时间复杂度为 O ( n ) O(n) O(n)。
查找元素
这种操作也很简答。如果是查找指定下标的元素,直接进行索引查找即可,时间复杂度为 O ( 1 ) O(1) O(1)。如果需要查找指定元素,那也不难,一次遍历即可,时间复杂度为 O ( n ) O(n) O(n)。
C++ STL 中的数组
在 C++ 标准库中定义两种类型的数组:array 和 vector。
array
array 是一种定长数组,也就是 C/C++ 中描述并使用的那种数组,使用之前要定义数组中的数据类型和固定的数组长度。
初始化
#include <iostream>
#include <array> // array 的头文件using namespace std;int main() {// 初始化列表 初始化 array<int, 7> myArr = {1, 4, 6, 8, 9, 1, 3};// 拷贝初始化array<int, 7> myArr2 = myArr;for (const auto& num : myArr2) {cout << num << " ";}return 0;
}
array 有两种初始化方法:初始化列表初始化和拷贝初始化。
重要的成员函数
| 成员函数 | 释义 |
|---|---|
| begin | 首迭代器 |
| end | 尾后迭代器 |
| size | 数组大小 |
| empty | 数组是否为空 |
| operator[] | 索引元素 |
| at | 索引元素 |
| font | 数组的第一个元素 |
| back | 数组的最后一个元素 |
| fill | 填充数组 |
| swap | 两个数组交换 |
vector
vector 是一种容器,是一种可变长的数据。当向 vector 容器中增加数据时,如果容器已经满了,那么它会重新在内存中找一块更大的连续内存来存放原来的数据。通常是按照原来内存的两倍大小进行扩容的。得益于自动扩容的特性,C++ 中多使用 vector 来构造数组。
初始化(构造函数)
#include <iostream>
#include <vector>int main () {// constructors used in the same order as described above:std::vector<int> first; // empty vector of intsstd::vector<int> second (4,100); // four ints with value 100std::vector<int> third (second.begin(),second.end()); // iterating through secondstd::vector<int> fourth (third); // a copy of third// the iterator constructor can also be used to construct from arrays:int myints[] = {16,2,77,29};std::vector<int> fifth (myints, myints + sizeof(myints) / sizeof(int) );std::cout << "The contents of fifth are:";for (std::vector<int>::iterator it = fifth.begin(); it != fifth.end(); ++it)std::cout << ' ' << *it;std::cout << '\n';return 0;
}
重要的成员函数
| 成员函数 | 释义 |
|---|---|
| begin | 首迭代器 |
| end | 尾后迭代器 |
| size | 数组大小 |
| capacity | 当前数组的存储容量 |
| empty | 数组是否为空 |
| reserve | 更改容量 |
| operator[] | 索引元素 |
| at | 索引元素 |
| font | 数组的第一个元素 |
| back | 数组的最后一个元素 |
| push_back | 在数组末尾增加元素 |
| pop_back | 删除最后一个元素 |
| clear | 清空容器 |
| swap | 两个数组交换 |
Python3 中的列表
python 中没有固定长度的数组,只有类似于 vector 容器的列表。
列表是一个有序且可更改的集合。集合中可以混合放置任意类型的元素,比如文本类型、数值类型和布尔类型,不要求必须放置同一类型的元素。
list1 = [8, "srt", 98, True]
此例中,列表 list1 包含了数值类型,文本类型和布尔类型的数据元素。
访问
可以通过索引来访问列表。
list1 = [8, "str", 98, True]print(list1[0]) # 输出 "str"
在 Python3 中索引可以是负值,负值索引表示从列表的末尾开始访问,-1 表示列表的最后一个元素,-2 表示列表的倒数第二个元素,等等。
list1 = [8, "str", 98, True]print(list1[-1]) # 输出列表的最后一个元素 True
范围索引
可以对列表指定起点、终点(取不到)和步长进行范围索引。
list2 = [1, 4, 5, 6]print(list2[0 : 3 : 2]) # 输出 [1, 5]
此例子对列表 list2 进行范围索引,从索引 0 开始,到索引 3 结束,每次在上一个索引的基础上 +2 进行访问。
负范围索引
范围索引还可以是负值。
list2 = [1, 4, 5, 6]print(list2[-4 : -1 : 2]) # 仍然输出 [1, 5]
此例子对列表 list2 进行负的范围索引,从倒数第 4 个元素开始索引,到倒数第一个元素结束(取不到),每次在上一个索引的基础上 +2 进行访问。
更改元素值
通过使用索引轻松更改元素值。
list2 = [1, 4, 5, 6]
list2[0] = 0 # 将列表第一个元素更改为 0print(list2) # 输出 [0, 4, 5, 6]
遍历列表
可以像 C/C++ 一样使用索引进行遍历,Python3 有自己的一种 for 遍历方法,C++ 中的 for 范围遍历对应的就是 Python3 中的范围遍历。
list3 = ["apple", "pear", "pineapple"]for x in list3:print(x)# 输出
"""
"apple"
"pear"
"pineapple"
"""
检查列表中是否存在某元素
如果需确定列表中是否存在指定的元素,使用 in 关键字:
list3 = ["apple", "pear", "pineapple"]if "apple" in list3:print("Yes, 'apple' is in the fruits list3.")
在此例中,如果文本 “apple” 在列表 list3 中,则 if 条件语句为 True,执行对应的语句,输出 "Yes, 'apple' is in the fruits list3.".
增加元素
如需将元素添加到列表的末尾,使用 append() 方法:
list3 = ["apple", "pear", "pineapple"]
list3.append("banana")print(list3) # 输出 ["apple", "pear", "pineapple", "banana"]
要在指定的索引处添加元素,使用 insert() 方法:
list4 = ["apple", "pear", "pineapple"]
list4.insert(1, "cherry")print(list4) # 输出 ["apple", "cherry", "pear", "pineapple"]
此例中,在列表 lsit4 的索引 1 处插入 “cherry”。
删除元素
通过 remove() 删除指定元素:
list5 = ["apple", "cherry", "pear", "pineapple"]
list5.remove("apple")print(list5) # 输出 ["cherry", "pear", "pineapple"]
通过 pop() 删除指定索引的元素(如果没有指定索引,则删除最后一项):
list6 = ["cherry", "pear", "pineapple"]
list6.pop()print(list6) # 输出 ["cherry", "pear"]
使用 del 关键字删除指定的索引,del 关键字也能完整地删除列表:
list7 = ["cherry", "pear", "pineapple"]
del list7[0]
print(list7) # 输出 ["pear", "pineapple"]del list7 # 直接删除 list7
使用 clear() 方法清空列表,这一点和 vector 中的 `clear() 一样:
list8 = ["apple", "banana", "cherry"]
list8.clear()print(list8) # 输出 []
拷贝列表
拷贝列表分为浅拷贝和深拷贝。见 Python之赋值、深拷贝与浅拷贝
总结 Python3 列表的常用操作
| 关键字 | 释义 |
|---|---|
| list() | 生成列表 |
| append() | 在列表尾追加元素 |
| insert() | 在指定位置插入元素 |
| pop() | 移除列表尾元素 |
| remove() | 移除列表中指定元素 |
| clear() | 清空列表 |
| del | 清空指定元素或列表 |
| + | 合并两个列表 |
| extend() | 在一个列表后追加另一个列表 |
| len() | 列表的长度 |
| sort() | 排序(默认升序) |
| reverse() | 反转列表 |
| copy() | 浅拷贝 |
| copy.deepcopy() | 深拷贝 |
参考资料
【文章】01. 数组基础知识
【文章】Python 列表
写在最后
如果您发现文章有任何错误或者对文章有任何疑问,欢迎私信博主或者在评论区指出 💬💬💬。
如果大家觉得有些地方需要补充,欢迎评论区交流。
最后,感谢您的阅读,如果有所收获的话可以给我点一个 👍 哦。
相关文章:
【算法与数据结构】数组
文章目录 前言数组数组的定义数组的基本操作增加元素删除元素修改元素查找元素 C STL 中的数组arrayvector Python3 中的列表访问更改元素值遍历列表检查列表中是否存在某元素增加元素删除元素拷贝列表总结 Python3 列表的常用操作 参考资料写在最后 前言 本系列专注更新基本数…...
【数据结构】队列详解(Queue)
文章目录 有关队列的概念队列的结点设计及初始化队列的销毁判空和计数入队操作出队操作 有关队列的概念 队列:只允许在一端进行插入数据操作,在另一端进行删除数据操作的特殊线性表,队列具有先进先出FIFO(First In First Out)入队列:进行插入操作的一端…...
Baumer工业相机堡盟工业相机如何通过NEOAPISDK获取相机的Statistics图像传输统计信息(C#)
Baumer工业相机堡盟工业相机如何通过NEOAPISDK获取相机的Statistics图像传输统计信息(C#) Baumer工业相机Baumer工业相机NEOAPI SDK和相机Statistics图像传输统计信息的技术背景Baumer工业相机通过NEOAPISDK获取相机的Statistics图像传输统计信息技术1.引…...
FreeRTOS标准库例程代码
1.设备STM32F103C8T6 2.工程模板 单片机: 部分单片机的程序例程 - Gitee.comhttps://gitee.com/lovefoolnotme/singlechip/tree/master/STM32_FREERTOS/1.%E5%B7%A5%E7%A8%8B%E6%A8%A1%E6%9D%BF 3.代码 1-FreeRTOS移植模板 #include "system.h" #include "…...
wandb: - 0.000 MB of 0.011 MB uploaded持续出现的解决方案
大家好,我是爱编程的喵喵。双985硕士毕业,现担任全栈工程师一职,热衷于将数据思维应用到工作与生活中。从事机器学习以及相关的前后端开发工作。曾在阿里云、科大讯飞、CCF等比赛获得多次Top名次。现为CSDN博客专家、人工智能领域优质创作者。喜欢通过博客创作的方式对所学的…...
分布式模式让业务更高效、更安全、更稳定
🌈 个人主页:danci_ 🔥 系列专栏:《设计模式》 💪🏻 制定明确可量化的目标,坚持默默的做事。 🚀 转载自热榜文章🔥:探索设计模式的魅力:分布式模…...
5.11学习记录
20长安杯部分 检材 1 的操作系统版本 CentOS Linux 7.6.1810 (Core) 检材 1 中,操作系统的内核版本是 3.10.0-957.el7.x86_64 检材 1 中磁盘包含一个 LVM 逻辑卷,该 LVM 开始的逻辑区块地址(LBA)是 2099200 物理卷ÿ…...
Java类加载器介绍
在Java中,类加载器是一种动态加载类的机制,它负责在运行时查找、加载和链接类文件。当Java应用程序需要创建某个类的对象时,类加载器会在运行时查找该类对应的.class文件,并将其加载到Java虚拟机中。Java类加载器通常分为三层&…...
VC++ PDH/性能计数器
例子: PID0,缺省为当前进程,但最好是获取当前进程ID传递进去,当然也可以选择其它进程的ID。 PerformanceCounter pc; pc.Open(0, "//Processor(_Total)//% Processor Time"); 源实现: #include <windo…...
C++ 类和对象:面向对象编程基础
目录标题 1. 什么是类?2. 什么是对象?3. 如何定义一个类?4. 如何创建对象?5. 类的构造函数6. 类的析构函数7. 数据封装和访问修饰符8. 示例:一个简单的BankAccount类9. 使用g编译10. 再来一个简单的C程序11. 定义书籍类…...
linux 基础命令使用
命令 su 用于切换到另一个用户身份,通常是超级用户(root)。su命令可以用来在命令行下切换用户,也可以在脚本中使用。 语法: su [选项] [用户名] 选项: - -c:执行完命令后,立即退出su命令;…...
eve 导入linux
mkdir /opt/unetlab/addons/qemu/linux-centos7 cd /opt/unetlab/addons/qemu/linux-centos7 上传hda.qcow2 /opt/unetlab/wrappers/unl_wrapper -a fixpermissions Linux images - (eve-ng.net) Due to very high demand of this section and problems with how to crea…...
vivado新版本兼容老版本,vitis classic兼容sdk教程
new version: vivado版本2023.2 和vitisv classic 2023.2 old version: vivado 2018.3以及之前的版本 打开工程 自动升级到当前版本,选择OK 点击Yes,合并当前的目录架构 点击OK 点击Report IP status 勾选要升级的IP核,点击升级 在项目工程文件夹…...
02.02.返回倒数第k个节点
实现一种算法,找出单向链表中倒数第 k 个节点。返回该节点的值。 注意:本题相对原题稍作改动 示例: 输入: 1->2->3->4->5 和 k 2 输出: 4 说明: 给定的 k 保证是有效的。 代码ÿ…...
MongoDB 从部署到掌握
一、docker部署MongoDB ## 通过docker安装MongoDB~~~shell #拉取镜像 docker pull mongo:4.0.3#创建容器 docker create --name mongodb-server -p 27017:27017 -v mongodb-data:/data/db mongo:4.0.3 --auth#启动容器 docker start mongodb-server#进入容器 docker exec -it …...
electron-vite工具打包后通过内置配置文件动态修改接口地址实现方法
系列文章目录 electronvitevue3 快速入门教程 文章目录 系列文章目录前言一、实现过程二、代码演示1.resources/env.json2.App.vue3.main/index.js4.request.js5.安装后修改 前言 使用electron-vite 工具开发项目打包完后每次要改接口地址都要重新打包,对于多环境…...
每日一练2024.5.9
题目: 给定一副牌,每张牌上都写着一个整数。 此时,你需要选定一个数字 X,使我们可以将整副牌按下述规则分成 1 组或更多组: 每组都有 X 张牌。组内所有的牌上都写着相同的整数。 仅当你可选的 X > 2 时返回 tru…...
P2622 关灯问题
小小注解: 1. vis:表示到达该状态的步数(min)1, 因为我们是从开始状态 穷举,所以每次到一个新状态(之前没有到过的状态)就是最小步数。 如何判断是否是一个新状态呢,…...
从头开始的建材类电商小程序开发指南
在当今数字化时代,小程序已经成为了许多企业推广和销售的重要渠道。对于建筑材料行业来说,开发一个属于自己的小程序商城不仅可以提升产品曝光度,还可以提供更好的用户购物体验。下面,我们将逐步教你如何开发建筑材料行业小程序。…...
数据结构中的栈(C语言版)
一.栈的概念 栈是一种常见的数据结构,它遵循后进先出的原则。栈可以看作是一种容器,其中的元素按照一种特定的顺序进行插入和删除操作。 压栈:栈的插入操作叫做进栈/压栈/入栈,入数据在栈顶。 出栈:栈的删除操作叫做…...
React Native在HarmonyOS 5.0阅读类应用开发中的实践
一、技术选型背景 随着HarmonyOS 5.0对Web兼容层的增强,React Native作为跨平台框架可通过重新编译ArkTS组件实现85%以上的代码复用率。阅读类应用具有UI复杂度低、数据流清晰的特点。 二、核心实现方案 1. 环境配置 (1)使用React Native…...
STM32标准库-DMA直接存储器存取
文章目录 一、DMA1.1简介1.2存储器映像1.3DMA框图1.4DMA基本结构1.5DMA请求1.6数据宽度与对齐1.7数据转运DMA1.8ADC扫描模式DMA 二、数据转运DMA2.1接线图2.2代码2.3相关API 一、DMA 1.1简介 DMA(Direct Memory Access)直接存储器存取 DMA可以提供外设…...
听写流程自动化实践,轻量级教育辅助
随着智能教育工具的发展,越来越多的传统学习方式正在被数字化、自动化所优化。听写作为语文、英语等学科中重要的基础训练形式,也迎来了更高效的解决方案。 这是一款轻量但功能强大的听写辅助工具。它是基于本地词库与可选在线语音引擎构建,…...
Aspose.PDF 限制绕过方案:Java 字节码技术实战分享(仅供学习)
Aspose.PDF 限制绕过方案:Java 字节码技术实战分享(仅供学习) 一、Aspose.PDF 简介二、说明(⚠️仅供学习与研究使用)三、技术流程总览四、准备工作1. 下载 Jar 包2. Maven 项目依赖配置 五、字节码修改实现代码&#…...
A2A JS SDK 完整教程:快速入门指南
目录 什么是 A2A JS SDK?A2A JS 安装与设置A2A JS 核心概念创建你的第一个 A2A JS 代理A2A JS 服务端开发A2A JS 客户端使用A2A JS 高级特性A2A JS 最佳实践A2A JS 故障排除 什么是 A2A JS SDK? A2A JS SDK 是一个专为 JavaScript/TypeScript 开发者设计的强大库ÿ…...
NPOI Excel用OLE对象的形式插入文件附件以及插入图片
static void Main(string[] args) {XlsWithObjData();Console.WriteLine("输出完成"); }static void XlsWithObjData() {// 创建工作簿和单元格,只有HSSFWorkbook,XSSFWorkbook不可以HSSFWorkbook workbook new HSSFWorkbook();HSSFSheet sheet (HSSFSheet)workboo…...
深度学习之模型压缩三驾马车:模型剪枝、模型量化、知识蒸馏
一、引言 在深度学习中,我们训练出的神经网络往往非常庞大(比如像 ResNet、YOLOv8、Vision Transformer),虽然精度很高,但“太重”了,运行起来很慢,占用内存大,不适合部署到手机、摄…...
0x-3-Oracle 23 ai-sqlcl 25.1 集成安装-配置和优化
是不是受够了安装了oracle database之后sqlplus的简陋,无法删除无法上下翻页的苦恼。 可以安装readline和rlwrap插件的话,配置.bahs_profile后也能解决上下翻页这些,但是很多生产环境无法安装rpm包。 oracle提供了sqlcl免费许可,…...
全面解析数据库:从基础概念到前沿应用
在数字化时代,数据已成为企业和社会发展的核心资产,而数据库作为存储、管理和处理数据的关键工具,在各个领域发挥着举足轻重的作用。从电商平台的商品信息管理,到社交网络的用户数据存储,再到金融行业的交易记录处理&a…...
__VUE_PROD_HYDRATION_MISMATCH_DETAILS__ is not explicitly defined.
这个警告表明您在使用Vue的esm-bundler构建版本时,未明确定义编译时特性标志。以下是详细解释和解决方案: 问题原因: 该标志是Vue 3.4引入的编译时特性标志,用于控制生产环境下SSR水合不匹配错误的详细报告1使用esm-bundler…...
