【算法与数据结构】数组
文章目录
- 前言
- 数组
- 数组的定义
- 数组的基本操作
- 增加元素
- 删除元素
- 修改元素
- 查找元素
- 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语言版)
一.栈的概念 栈是一种常见的数据结构,它遵循后进先出的原则。栈可以看作是一种容器,其中的元素按照一种特定的顺序进行插入和删除操作。 压栈:栈的插入操作叫做进栈/压栈/入栈,入数据在栈顶。 出栈:栈的删除操作叫做…...
从零实现富文本编辑器#5-编辑器选区模型的状态结构表达
先前我们总结了浏览器选区模型的交互策略,并且实现了基本的选区操作,还调研了自绘选区的实现。那么相对的,我们还需要设计编辑器的选区表达,也可以称为模型选区。编辑器中应用变更时的操作范围,就是以模型选区为基准来…...
蓝桥杯 2024 15届国赛 A组 儿童节快乐
P10576 [蓝桥杯 2024 国 A] 儿童节快乐 题目描述 五彩斑斓的气球在蓝天下悠然飘荡,轻快的音乐在耳边持续回荡,小朋友们手牵着手一同畅快欢笑。在这样一片安乐祥和的氛围下,六一来了。 今天是六一儿童节,小蓝老师为了让大家在节…...
【磁盘】每天掌握一个Linux命令 - iostat
目录 【磁盘】每天掌握一个Linux命令 - iostat工具概述安装方式核心功能基础用法进阶操作实战案例面试题场景生产场景 注意事项 【磁盘】每天掌握一个Linux命令 - iostat 工具概述 iostat(I/O Statistics)是Linux系统下用于监视系统输入输出设备和CPU使…...
服务器硬防的应用场景都有哪些?
服务器硬防是指一种通过硬件设备层面的安全措施来防御服务器系统受到网络攻击的方式,避免服务器受到各种恶意攻击和网络威胁,那么,服务器硬防通常都会应用在哪些场景当中呢? 硬防服务器中一般会配备入侵检测系统和预防系统&#x…...
渲染学进阶内容——模型
最近在写模组的时候发现渲染器里面离不开模型的定义,在渲染的第二篇文章中简单的讲解了一下关于模型部分的内容,其实不管是方块还是方块实体,都离不开模型的内容 🧱 一、CubeListBuilder 功能解析 CubeListBuilder 是 Minecraft Java 版模型系统的核心构建器,用于动态创…...

高等数学(下)题型笔记(八)空间解析几何与向量代数
目录 0 前言 1 向量的点乘 1.1 基本公式 1.2 例题 2 向量的叉乘 2.1 基础知识 2.2 例题 3 空间平面方程 3.1 基础知识 3.2 例题 4 空间直线方程 4.1 基础知识 4.2 例题 5 旋转曲面及其方程 5.1 基础知识 5.2 例题 6 空间曲面的法线与切平面 6.1 基础知识 6.2…...
spring:实例工厂方法获取bean
spring处理使用静态工厂方法获取bean实例,也可以通过实例工厂方法获取bean实例。 实例工厂方法步骤如下: 定义实例工厂类(Java代码),定义实例工厂(xml),定义调用实例工厂ÿ…...
【git】把本地更改提交远程新分支feature_g
创建并切换新分支 git checkout -b feature_g 添加并提交更改 git add . git commit -m “实现图片上传功能” 推送到远程 git push -u origin feature_g...
高防服务器能够抵御哪些网络攻击呢?
高防服务器作为一种有着高度防御能力的服务器,可以帮助网站应对分布式拒绝服务攻击,有效识别和清理一些恶意的网络流量,为用户提供安全且稳定的网络环境,那么,高防服务器一般都可以抵御哪些网络攻击呢?下面…...

Java面试专项一-准备篇
一、企业简历筛选规则 一般企业的简历筛选流程:首先由HR先筛选一部分简历后,在将简历给到对应的项目负责人后再进行下一步的操作。 HR如何筛选简历 例如:Boss直聘(招聘方平台) 直接按照条件进行筛选 例如:…...