【算法与数据结构】数组

文章目录

  • 前言
  • 数组
    • 数组的定义
    • 数组的基本操作
      • 增加元素
      • 删除元素
      • 修改元素
      • 查找元素
    • 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 ints
  std::vector<int> second (4,100);                       // four ints with value 100
  std::vector<int> third (second.begin(),second.end());  // iterating through second
  std::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	# 将列表第一个元素更改为 0

print(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.mfbz.cn/a/612578.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Acrobat Pro DC 2023 for Mac:PDF处理的终极解决方案

Acrobat Pro DC 2023 for Mac为Mac用户提供了PDF处理的终极解决方案。它具备强大的文档处理能力&#xff0c;无论是查看、编辑还是创建PDF文件&#xff0c;都能轻松胜任。在编辑功能方面&#xff0c;Acrobat Pro DC 2023支持对文本、图像进行精准的修改和调整&#xff0c;还能添…

2024-05-10 Ubuntu上面使用libyuv,用于转换、缩放、旋转和其他操作YUV图像数据,测试实例使用I420ToRGB24

一、简介&#xff1a;libyuv 最初是由Google开发的&#xff0c;主要是为了支持WebRTC项目中的视频处理需求。用于处理YUV格式图像数据的开源库。它提供了一系列的函数&#xff0c;用于转换、缩放、旋转和其他操作YUV图像数据。 二、执行下面的命令下载和安装libyuv。 git clo…

杰发科技AC7801——ADC之Bandgap和内部温度计算

0. 参考 电流模架构Bandgap设计与仿真 bandgap的理解&#xff08;内部带隙电压基准&#xff09; ​ ​ 虽然看不懂这些公式&#xff0c;但是比较重要的一句应该是这个&#xff1a;因为传统带隙基准的输出值为1.2V ​ 1. 使用 参考示例代码。 40002000是falsh控制器寄…

LeetCode 112. 路径总和 || LeetCode 113. 路径总和ii

LeetCode 112. 路径总和 1、题目 题目链接&#xff1a;112. 路径总和 给你二叉树的根节点 root 和一个表示目标和的整数 targetSum 。判断该树中是否存在 根节点到叶子节点 的路径&#xff0c;这条路径上所有节点值相加等于目标和 targetSum 。如果存在&#xff0c;返回 true…

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

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

Win11安装Docker Desktop运行Oracle 11g 【详细版】

oracle docker版本安装教程 步骤拉取镜像运行镜像进入数据库配置连接数据库&#xff0c;修改密码Navicat连接数据库 步骤 拉取镜像 docker pull registry.cn-hangzhou.aliyuncs.com/helowin/oracle_11g运行镜像 docker run -d -p 1521:1521 --name oracle11g registry.cn-ha…

MySQL的表级锁

&#x1f4dd;个人主页&#xff1a;五敷有你 &#x1f525;系列专栏&#xff1a;面经 ⛺️稳中求进&#xff0c;晒太阳 表级锁 介绍 对于表锁&#xff0c;分为两类&#xff1a; 表共享读锁表独占写锁 语法 1. 加锁&#xff1a;lock tables 表名... read/write 2.…

Multitouch for Mac:手势自定义,提升工作效率

Multitouch for Mac作为一款触控板手势增强软件&#xff0c;其核心功能在于手势的自定义和与Mac系统的深度整合。通过Multitouch&#xff0c;用户可以轻松设置各种手势&#xff0c;如三指轻点、四指左右滑动等&#xff0c;来执行常见的任务&#xff0c;如打开应用、切换窗口、滚…

网络编程——Socket——模拟用户登录

功能一&#xff1a;模拟用户登录 功能二&#xff1a;实现客户发送登录用户信息&#xff0c;服务器端显示登录信息并响应给客户端登录成功 这里设置的用户登录信息为&#xff1a;admin&#xff0c;123456 实现&#xff1a; 1.首先&#xff0c;服务端创建并启动服务器&#x…

MyBatis——MyBatis入门程序

一、数据准备 二、开发步骤 1、引入依赖 <dependencies><dependency><groupId>org.mybatis</groupId><artifactId>mybatis</artifactId><version>3.5.15</version></dependency><dependency><groupId>c…

如何打开远程桌面连接?

远程桌面连接是一项强大的功能&#xff0c;它允许我们远程访问其他计算机&#xff0c;并在远程计算机上进行操作。这对于远程办公、技术支持和远程培训等场景非常有用。本文将介绍如何在不同操作系统中打开远程桌面连接。 Windows系统 在Windows操作系统中&#xff0c;打开远程…

算法练习day7

四数相加II 代码随想录 0454.四数相加II 454. 四数相加 II - 力扣&#xff08;LeetCode&#xff09; &#xff08;用时&#xff1a;0.5小时&#xff09; 思路 本道题是需要在四个数组中&#xff0c;各找一个数&#xff0c;这些数加起来能够等于0&#xff0c;那么就是答案元…

mysql基础概念

文章目录 登录mysqlmysql和mysqld数据库操作主流数据库MYSQL架构SQL分类 登录mysql 登录mysql连接服务器&#xff0c;mysql连接时可以指明主机用-h选项&#xff0c;然后就可以指定主机Ip地址&#xff0c;-P可以指定端口号 -u指定登录用户 -P指定登录密码 查看系统中有无mysql&…

【系统架构师】-选择题(十二)计算机网络

1、网闸的作用&#xff1a;实现内网与互联网通信&#xff0c;但内网与互联网不是直连的 2、管理距离是指一种路由协议的路由可信度。15表示该路由信息比较可靠 管理距离越小&#xff0c;它的优先级就越高&#xff0c;也就是可信度越高。 0是最可信赖的&#xff0c;而255则意味…

(Java)心得:LeetCode——11.盛最多水的容器

一、原题 给定一个长度为 n 的整数数组 height 。有 n 条垂线&#xff0c;第 i 条线的两个端点是 (i, 0) 和 (i, height[i]) 。 找出其中的两条线&#xff0c;使得它们与 x 轴共同构成的容器可以容纳最多的水。 返回容器可以储存的最大水量。 说明&#xff1a;你不能倾斜容…

【C++】CentOS环境搭建-安装CATCH2

【C】CentOS环境搭建-安装CATCH2 1.克隆Catch2仓库2. 进入Catch2目录3. 创建一个构建目录4. 使用CMake生成构建系统&#xff08;以及可能的编译&#xff09;5.安装Catch2&#xff08;可选&#xff0c;根据你的需求&#xff09; 1.克隆Catch2仓库 git clone https://github.com…

ansible部署lamp架构

搭建参考&#xff1a;ansible批量运维管理-CSDN博客 定义ansible主机清单 [rootansible-server ~]# vim /etc/hosts 192.168.200.129 host01 192.168.200.130 host02 [rootansible-server ~]# vim /etc/ansible/hosts [webserver] host01 host02 在ansible端编写index.html…

08.1.自定义图形

自定义图形 创建图形 随便选择几个参数直接添加 选择自定义折线图形查看

一键追爆款,GPT一键改文‌‍‬⁣⁡​⁤⁢​⁢⁡⁣‬‍‌​​‬ ​‍⁤‬ ‬⁡⁡⁡‍‌‬⁡⁡⁢‬⁤⁢⁢⁤​‍‌​​‬ ​⁣‌,绘唐3,绘唐工具

ai画影满足你的制作要求 一键追爆款&#xff0c;GPT一键改文 AI推文小说&漫画解说&解压混剪 人物定义&#xff0c;角色定义&#xff0c;lora转换&#xff0c;模型转换&#xff0c;可视化参考满足 一键追爆款 一键挂机生成&#xff0c;效果更精彩&#xff0c;使用更方…

苹果电脑怎么安装crossover 如何在Mac系统中安装CrossOver CrossOver Mac软件安装说明

很多Mac的新用户在使用电脑的过程中&#xff0c;常常会遇到很多应用软件不兼容的情况。加上自己以前一直都是用Windows系统&#xff0c;总觉得Mac系统用得很难上手。 其实&#xff0c;用户可以在Mac上安装CrossOver&#xff0c;它支持用户在Mac上运行Windows软件&#xff0c;例…