【算法与数据结构】数组

文章目录

  • 前言
  • 数组
    • 数组的定义
    • 数组的基本操作
      • 增加元素
      • 删除元素
      • 修改元素
      • 查找元素
    • 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 列表


写在最后

如果您发现文章有任何错误或者对文章有任何疑问,欢迎私信博主或者在评论区指出 💬💬💬。

如果大家觉得有些地方需要补充,欢迎评论区交流。

最后,感谢您的阅读,如果有所收获的话可以给我点一个 👍 哦。

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

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

相关文章

从0开始Jmeter接口测试实战

在之前的文章中给大家介绍过接口测试文档和接口测试用例示例&#xff0c;本文基于Jmeter工具给大家介绍一下如何实现接口测试用例&#xff1a;包括发起Http请求&#xff0c;绕过登陆&#xff0c;验证响应。JMeter是Apache组织开发的基于Java的压力测试工具。具有开源免费、框架…

Leetcode—2105. 给植物浇水 II【中等】

2024每日刷题&#xff08;131&#xff09; Leetcode—2105. 给植物浇水 II 实现代码 class Solution { public:int minimumRefill(vector<int>& plants, int capacityA, int capacityB) {int size plants.size();int i 0;int j size - 1;int capA capacityA;in…

【Linux】Linux安装JDK

一、卸载Linux自带的JDK #查询已有的JDK rpm -qa | grep jdk ①将查询到的JDK全部卸载掉 #直接复制一整行的JDK名称 yum -y remove java-1.7.0-openjdk-headless-1.7.0.261-2.6.22.2.el7_8.x86_64 ②卸载完第一个后再次查询 ③继续卸载&#xff0c;卸载完成后再次查询 ④查询…

Flask-大体了解介绍

初识Flask Flask是使用 Python编写的Web微框架。Web框架可以让我们不用关心底层的请求响应处理&#xff0c;更方便高效地编写Web程序。 Flask主要有两个依赖&#xff0c;一个是WSGI&#xff08;Web Server Gateway Interface&#xff0c;Web服务器网关接口&#xff09;工具集…

ICode国际青少年编程竞赛- Python-4级训练场-太阳能板1

ICode国际青少年编程竞赛- Python-4级训练场-太阳能板1 1、 Dev.step(3) Dev.turnRight() Dev.step(2) while Dev.energy < 60:wait() Dev.step(-6)2、 Dev.step(7) while Dev.energy < 90:wait() Dev.step(-1) Dev.turnRight() Dev.step(7)3、 Dev.step(4) Dev.turn…

区块链 | NFT 水印:Review on Watermarking Techniques(三)

&#x1f34d;原文&#xff1a;Review on Watermarking Techniques Aiming Authentication of Digital Image Artistic Works Minted as NFTs into Blockchains 一个 NFT 的水印认证协议 可以引入第三方实体来实现对交易的认证&#xff0c;即通过使用 R S A \mathsf{RSA} RSA…

(十)JSP教程——config对象

config对象是脚本程序配置对象&#xff0c;表示当前JSP页面的配置信息。由于JSP页面通常无需配置&#xff0c;因此该对象在JSP页面中比较少见。 config对象可以读取一些初始化参数的值&#xff0c;而这些参数一般在web.xml配置文件中可以看到&#xff0c;并通过config对象的相应…

国内护眼台灯品牌哪些实用?推荐五款物美价廉的台灯品牌

近年来&#xff0c;我们注意到儿童近视的现象呈现出增多且趋于低龄化的趋势。这一变化&#xff0c;部分原因可以归咎于孩子们越来越多地使用电子产品&#xff0c;另一部分则与他们面临的学业压力增加有关。鉴于此&#xff0c;家长们在挑选儿童学习用品时变得格外谨慎&#xff0…

Sqli-labs第五~八关(布尔盲注)

目录 首先找到他们的闭合方式 操作 总结&#xff1a; 第五关根据页面结果得知是字符型但是和前面四关还是不一样是因为页面虽然有东西。但是只有对于请求对错出现不一样页面其余的就没有了。这个时候我们用联合注入就没有用&#xff0c;因为联合注入是需要页面有回显位。如果…

鸿蒙开发接口Ability框架:【@ohos.application.Want (Want)】

Want Want模块提供系统的基本通信组件的能力。 说明&#xff1a; 本模块首批接口从API version 8 开始支持。后续版本的新增接口&#xff0c;采用上角标单独标记接口的起始版本。 导入模块 import Want from ohos.application.Want; 开发前请熟悉鸿蒙开发指导文档&#xff1…

nginx--rewrite

功能 Nginx服务器利用ngx_http_rewrite_module 模块解析和处理理rewrite请求&#xff0c;此功能依靠PCRE(Perl Compatible Regular Expressions)&#xff0c;因此编译之前要安装PCRE库&#xff0c;rewrite是nginx服务器的重要功能之一&#xff0c;用于实现URL的重写&#xff0…

《Video Mamba Suite》论文笔记(4)Mamba在时空建模中的作用

原文翻译 4.4 Mamba for Spatial-Temporal Modeling Tasks and datasets.最后&#xff0c;我们评估了 Mamba 的时空建模能力。与之前的小节类似&#xff0c;我们在 Epic-Kitchens-100 数据集 [13] 上评估模型在zero-shot多实例检索中的性能。 Baseline and competitor.ViViT…

【网络编程】UDP协议和TCP协议1

UDP协议格式 UDP 报文分为 UDP 报头和 UDP 数据区两部分。报头由 4 个 16 位长&#xff08;2字节&#xff09;字段组成&#xff0c;分别说明该报文的源端口、目的端口、报文长度和校验值。 UDP协议如何将报头和有效载荷分离 UDP报头是一种定长报头&#xff0c;长度为8个字节。…

QCC3071/QCC3081/QCC3083/QCC3084/QCC5171/QCC5181/QCC3091/QCC3095平台LDAC解码

QCC3071/QCC3081/QCC3083/QCC3084/QCC5171/QCC5181/QCC3091/QCC3095平台LDAC解码 LDAC Decoder Evaluation Kit for QCC5181 and QCC5171 (The 5181 Kit) 随着Qualcomm DSP向下开放&#xff0c;QCC3071/QCC3081/QCC3083/QCC3084目前可以可以实现LDAC Decoder。 QCC3071/QCC3…

【Shell脚本】Shell编程之循环语句

目录 一.循环语句 1.for语句的结构 1.1.格式 1.2.实操案例 案例1. 案例2. 案例3. 案例4. 2.while语句的结构 2.1.格式 2.2.实操案例 案例1. 案例2. 案例3. 案例4. 3.until循环命令 3.1.格式 3.2.实操案例 案例1. 二.补充 1.常用转义符 一.循环语句 1.for…

56 关于 linux 的 oom killer 机制

前言 这里主要讲的是 linux 的 oom killer 机制 在系统可用内存较少的情况下&#xff0c;内核为保证系统还能够继续运行下去&#xff0c;会选择杀掉一些进程释放掉一些内存。 通常oom_killer的触发流程是&#xff1a;进程A想要分配物理内存&#xff08;通常是读写内存&#…

笨方法自学python(九)-读写文件

读取文件 前面已经学过了 input 和 argv&#xff0c;这些是你开始学习读取文件的必备基础。你可能需要多多实验才能明白它的工作原理&#xff0c;这节练习涉及到写两个文件。一个正常的 ex15.py 文件&#xff0c;另外一个是 ex15_sample.txt&#xff0c;第二个文件并不是脚本&…

图像锐化——非锐化掩膜USM和锐化掩膜SM(附代码)

非锐化掩膜 (USM) 和锐化掩膜 (SM) 都是常用的图像锐化技术。它们都可以通过增强图像的边缘信息来提高图像的清晰度。 目录 一、非锐化掩膜USM1.1 USM原理1.2 USM实现步骤1.3 优点1.4 代码 二、锐化掩膜SM2.1 SM原理2.2 SM实现步骤2.3 优点2.4 代码 三、锐化效果四、总结4.1 效…

Qt三方库:QuaZIP介绍、编译和使用

前言 Qt使用一些压缩解压功能&#xff0c;探讨过libzip库&#xff0c;zlib库&#xff0c;libzip库比较原始&#xff0c;还有其他库&#xff0c;都比较基础&#xff0c;而在基础库之上&#xff0c;又有高级封装库&#xff0c;Qt中的QuaZIP是一个很好的选择。Quazip是一个用于压缩…

5.11学习记录

20长安杯部分 检材 1 的操作系统版本 CentOS Linux 7.6.1810 (Core) 检材 1 中&#xff0c;操作系统的内核版本是 3.10.0-957.el7.x86_64 检材 1 中磁盘包含一个 LVM 逻辑卷&#xff0c;该 LVM 开始的逻辑区块地址&#xff08;LBA&#xff09;是 2099200 物理卷&#xff…