【算法与数据结构】数组

文章目录

  • 前言
  • 数组
    • 数组的定义
    • 数组的基本操作
      • 增加元素
      • 删除元素
      • 修改元素
      • 查找元素
    • 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://xiahunao.cn/news/3029751.html

如若内容造成侵权/违法违规/事实不符,请联系瞎胡闹网进行投诉反馈,一经查实,立即删除!

相关文章

uniapp的app端推送功能,不使用unipush

1&#xff1a;推送功能使用htmlPlus实现&#xff1a;地址HTML5 API Reference (html5plus.org) 效果图&#xff1a; 代码实现&#xff1a; <template><view class"content"><view class"text-area"><button click"createMsg&q…

跨界内容营销:Kompas.ai如何帮助你的品牌打破行业边界

在当今多元化的市场环境中&#xff0c;跨界营销已成为品牌拓展影响力和用户基础的重要策略。通过跨界合作&#xff0c;品牌能够打破行业界限&#xff0c;创造独特的用户体验&#xff0c;从而提升品牌形象和市场竞争力。本文将深入分析跨界营销的作用&#xff0c;详细介绍Kompas…

AI-powered的搜索引擎:Perplexity 与知识工作者

Perplexity是一款AI-powered的搜索引擎&#xff0c;通过与OpenAI合作&#xff0c;利用GPT模型提供高速、准确的搜索结果&#xff0c;特别针对知识工作者的需求进行优化。 知识工作者通常需要进行复杂的研究和决策&#xff0c;他们希望能够快速获取准确的信息来支持他们的工作。…

buuctf-misc题目练习三

荷兰宽带数据泄露 BIN 文件&#xff0c;也称为二进制文件&#xff0c;是一种压缩文件格式&#xff0c;可以 包含图像和视频等信息 , 并被许多应用程序用于各种目的。 RouterPassView是一个找回路由器密码的工具。 大多数现代路由器允许备份到一个文件路由器的配置&#xff0c…

Unity TileMap入门

概述 相信很多同学学习制作游戏都是从2D游戏开始制作的吧&#xff0c;瓦片地图相信大家都有接触&#xff0c;那接下来让我们学习一下这部分的内容吧&#xff01; Tilemap AnimationFrameRate:设置每帧动画的播放速率。Color:瓦片地图的颜色TileAnchor:锚点&#xff0c;&#x…

100000订单直接拒掉,君子爱财,取之有道

近一个月询盘可谓寥寥无几&#xff0c;成交率为0&#xff0c;今天好不容易接了一个客户询盘&#xff0c;订单总价高达100000&#xff0c;听完细节直接拒掉&#xff0c;至于原因懂的都懂&#xff0c;不懂得等我慢慢道来。 前两天有2个询盘&#xff0c;其中一个是二次开发&#x…

正点原子[第二期]Linux之ARM(MX6U)裸机篇学习笔记-15.4讲 GPIO中断实验-IRQ中断服务函数详解

前言&#xff1a; 本文是根据哔哩哔哩网站上“正点原子[第二期]Linux之ARM&#xff08;MX6U&#xff09;裸机篇”视频的学习笔记&#xff0c;在这里会记录下正点原子 I.MX6ULL 开发板的配套视频教程所作的实验和学习笔记内容。本文大量引用了正点原子教学视频和链接中的内容。…

如何利用代理IP进行SEO优化?

“SEO”这个词相信对于做在线业务的朋友来说一定不陌生。 在网络营销中&#xff0c;SEO是至关重要的一环&#xff0c;对于增加有机流量、提升品牌知名度、增加网站的信任度和权威性非常有效。而代理IP在SEO优化中有着不可或缺的作用&#xff0c;它可以帮助网站管理员和SEO专家…

数据中心法

数据中心法是实现词法分析器的结构化方法。通过设计主表和子表分开存储状态转移信息&#xff0c;实现词法分析器的控制逻辑和数据结构分离。 主要解决了状态爆炸、难以维护和复杂性的问题。 状态爆炸是指当状态和转移较多时&#xff0c;单一使用一个表来存储所有的信息的话会导…

这3种深拷贝实现,你都知道吗?

目录&#xff1a; 1、JSON.parse 2、structuredClone 3、cloneDeep

Leetcode—138. 随机链表的复制【中等】(cend函数)

2024每日刷题&#xff08;129&#xff09; Leetcode—138. 随机链表的复制 实现代码 /* // Definition for a Node. class Node { public:int val;Node* next;Node* random;Node(int _val) {val _val;next NULL;random NULL;} }; */class Solution { public:Node* copyRan…

【vivado】debug相关时钟及其约束关系

一、前言 在xilinx fpga的degug过程中&#xff0c;经常出现由于时钟不对而导致的观测波形失败&#xff0c;要想能够解决这些问题需要了解其debug的组成环境以及之间的数据流。本文主要介绍debug过程中需要的时钟及各时钟之间的关系。 二、debug相关时钟 Vivado 硬件管理器使…

【CCF-CSP】202403-3 化学方程式配平

输入格式&#xff1a; 从标准输入读入数据。 输入的第一行包含一个正整数 n&#xff0c;表示需要判断的化学方程式的个数。 接下来的 n 行&#xff0c;每行描述了一个需要被配平的化学方程式。包含空格分隔的一个正整数和全部涉及物质的化学式。其中&#xff0c;正整数 m 表…

KMeans,KNN,Mean-shift算法的学习

1.KMeans算法是什么&#xff1f; 在没有标准标签的情况下&#xff0c;以空间的k个节点为中心进行聚类&#xff0c;对最靠近他们的对象进行归类。 2.KMeans公式&#xff1a; 2. 1.关键分为三个部分&#xff1a; 1.一开始会定义n个中心点&#xff0c;然后计算各数据点与中心点…

企业活动想联系媒体报道宣传如何联系媒体?

在企业的宣传推广工作中,我曾经历过一段费事费力、效率极低的时期。那时,每当公司有重要活动或新项目需要媒体报道时,我便要一家家地联系媒体,发送邮件、打电话,甚至亲自登门拜访,只为求得一篇报道。然而,这样的过程充满了不确定性和挑战,时常让我感到焦虑和压力山大。 记得有一…

在CentOS 7服务器及Windows 10客户端间建立并配置NFS服务

在CentOS 7服务器及Windows 10客户端间建立并配置NFS服务 引言 网络文件系统(Network File System)&#xff0c;简称NFS&#xff0c;是一种分布式文件系统协议。它允许网络上的客户端机器像访问本地磁盘文件一样&#xff0c;通过网络访问服务器上的文件。在某些特定的业务场景中…

鸿蒙内核源码分析(文件句柄篇) | 你为什么叫句柄

句柄 | handle int open(const char* pathname,int flags); ssize_t read(int fd, void *buf, size_t count); ssize_t write(int fd, const void *buf, size_t count); int close(int fd);只要写过应用程序代码操作过文件不会陌生这几个函数,文件操作的几个关键步骤嘛,跟把大…

202466读书笔记|《一天一首古诗词》——借问梅花何处落,风吹一夜满关山

202466读书笔记|《一天一首古诗词》——借问梅花何处落&#xff0c;风吹一夜满关山 上册下册 《一天一首古诗词》作者李锡琴&#xff0c;蛮早前加入书架的已购买书籍&#xff0c;这次刚好有点时间&#xff0c;利用起来读完。 赏析没有细看&#xff0c;只读了诗词部分&#xff0…

上海AI Lab开源首个可替代GPT-4V的多模态大模型

与开源和闭源模型相比&#xff0c;InternVL 1.5 在 OCR、多模态、数学和多轮对话等 18 个基准测试中的 8 个中取得了最先进的结果。 上海AI Lab 推出的 InternVL 1.5 是一款开源的多模态大语言模型 (MLLM)&#xff0c;旨在弥合开源模型和专有商业模型在多模态理解方面的能力差距…