三、数组————相关概念详解


数组

  • 前言
  • 一、数据理论基础
  • 二、数组常用操作
    • 2.1 初始化数组
    • 2.2 访问数组中的元素
    • 2.3 插入元素
    • 2.4 删除元素
  • 三、数组扩展
    • 3.1 遍历数组
    • 3.2 数组扩容
  • 总结
    • 1、数组的优点
    • 2、数组的不足


前言

  • 在数据结构中,数组可以算得上最基本的数据结构。
  • 数组可以用于实现栈、队列、哈希表、堆、图等数据结构。例如,图的邻接矩阵表示实际上是一个二维数组。(后续我们再讲)

一、数据理论基础

  • 学习数组之前我们首先要了解数组在内存中的存储方式,这样才能真正理解数组的相关操作
    数组是储存在连续内存空间的相同类型的数据的集合,举一个字符数组的例子,如下图所示
    在这里插入图片描述
  • 观察上图,我们发现数组首个元素的索引为 0,这似乎有些反直觉,因为从 1 开始计数会更自然。那是因为,索引本质上是内存地址的偏移量。首个元素的地址偏移量是 0,因此它的索引为 0 是合理的。

二、数组常用操作

2.1 初始化数组

  • 我们可以根据需求选用数组的两种初始化方式:无初始值、给定初始值。在未指定初始值的情况下,大多数编程语言会将数组元素初始化为 0

代码如下(示例):

# 初始化数组
arr: list[int] = [0] * 5            # [ 0, 0, 0, 0, 0 ]
nums: list[int] = [1, 3, 2, 5, 4]   # [1, 3, 2, 5, 4]

2.2 访问数组中的元素

  • 数组元素被存储在连续的内存空间中,这意味着计算数组元素的内存地址非常容易。
    在这里插入图片描述
  • 从上图中我们知道,我们只要知道数组第一位元素地址跟某元素的索引就可以轻松的算出来该元素的地址。
计算公式
元素内存地址 = 数组内存地址(即第一位元素的地址) + 元素长度(因为存的都是相同类型的元素,所以长度一样) x 元素索引
譬如求数组中 E 的元素的内存地址
16 = 00 + 4 x 4

代码如下(示例):

# 导包
import random
# 定义数组列表
list1: list[int] = [1, 3, 2, 5, 4]def random_access(list1: list[int]) -> int:"""随机访问数组中的元素演示:param list1: 接受 数组 :return: 返回数组中的随机一个元素"""# 在区间 [0, len(nums)-1] 中随机抽取一个数字random_index = random.randint(0, len(list1) - 1)# 获取并返回随机元素random_num = list1[random_index]return random_numif __name__ == '__main__':res = random_access(list1)print(res)

数组中访问元素非常高效,我们可以在 O(1) 时间内访问数组中的任意一个元素

2.3 插入元素

  • 因为数组中的元素在内存中是连续存在的,所以插入元素的时候,需要将插入位置后的所有元素都往后移动一位,之后再将元素赋值给该索引,如下图所示:
    在这里插入图片描述
    因为数组的长度是固定的,因此插入元素的时候,必定导致尾部元素丢失,这个我们在列表中在进行讨论。

代码如下(示例):

def insert(nums, num, index):"""在数组的索引 index 处插入元素 num:param nums: 接受的数组:param num: 要插入的元素:param index: 要插入的位置(索引):return: 无返回值""""""在数组的索引 index 处插入元素 num"""# 把索引 index 以及之后的所有元素向后移动一位for i in range(len(nums) - 1, index, -1):nums[i] = nums[i - 1]# 将 num 赋给 index 处的元素nums[index] = numif __name__ == '__main__':nums = ['A', 'B', 'C', 'D', '']print(f'插入前的数组为{nums}')   # ['A', 'B', 'C', 'D', '']insert(nums, 'E', 1)print(f'插入前的数组为{nums}')   # ['A', 'E', 'B', 'C', 'D']

2.4 删除元素

  • 跟插入元素相同,删除元素也需要移动元素
  • 数组中元素不能删除,只能覆盖
  • 若删除索引 1 处的元素,就要将索引 1 之后的元素都往前移动一位,如下图所示:
    在这里插入图片描述
    删除 E 后, 你会发现数组中最后有两个 D ,这个我们之后在讨论

代码如下(示例):

def remove(nums, index):"""删除索引 index 处的元素:param nums: 传入的数组:param index: 要删除的元素的索引:return: 无"""# 把索引 index 之后的所有元素向前移动一位for i in range(index, len(nums) - 1, 1):nums[i] = nums[i + 1]if __name__ == '__main__':nums = ['A', 'E', 'B', 'C', 'D']print(f'删除前的数组为{nums}')   # ['A', 'E', 'B', 'C', 'D']remove(nums, 1)print(f'删除后的数组为{nums}')   # ['A', 'B', 'C', 'D', 'D']

三、数组扩展

3.1 遍历数组

  • 我们既可以通过索引遍历数组,也可以直接遍历获取数组中的每个元素

代码如下(示例):

def traverse1(nums):"""遍历数组"""count = 0# 通过索引遍历数组for i in range(len(nums)):print(nums[i])count += 1def traverse2(nums):# 直接遍历数组元素for num in nums:print(num)def traverse3(nums):# 同时遍历数据索引和元素# enumerate()函数会返回一个枚举对象,这个对象包含了列表中每个元素的索引和值。# enumerate函数默认从0开始计数索引,如果你需要从其他的数字开始,可以通过传递一个可选的起始参数来实现。for i, num in enumerate(nums):print(f'索引是{i},对应的元素是{num}')if __name__ == '__main__':nums = ['A', 'B', 'C', 'D', 'E']traverse1(nums)   #  A   B   C    D    E traverse2(nums)   #  A   B   C    D    E traverse3(nums)   #  A   B   C    D    E 

3.2 数组扩容

  • 在Python中数组的长度是不可变的,因为程序难以保证数组之后的内存空间是可用的,从而无法安全地扩展数组容量。
  • 如果我们想要扩容数组的话,只能重新建立一个新数组,然后将原数组的元素依次复制到新数组,这是一个时间复杂度为 O ( n ) O(n) O(n)的操作,当数组很大的时候,很消耗时间。

代码如下(示例):

def extend(nums, enlarge):"""扩展数组长度:param nums: 原数组:param enlarge: 要扩多大的空间:return: 返回扩容后的新数组"""# 初始化一个扩展长度后的数组res = [0] * (len(nums) + enlarge)# 将原数组中的所有元素复制到新数组for i in range(len(nums)):res[i] = nums[i]# 返回扩展后的新数组return resif __name__ == '__main__':nums = ['A', 'B', 'C', 'D', 'E']print(f'扩容前的数组为{nums}') # ['A', 'B', 'C', 'D', 'E']res = extend(nums, 3)print(f'扩容后的数组为{res}')  # ['A', 'B', 'C', 'D', 'E', 0, 0, 0]

总结

1、数组的优点

  • 空间效率高:数组为数据分配了连续的内存块,无须额外的结构开销。
  • 支持随机访问:数组允许在 O ( 1 ) O(1) O(1) 时间内访问任何元素。
  • 缓存局部性:当访问数组元素时,计算机不仅会加载它,还会缓存其周围的其他数据,从而借助高速缓存来提升后续操作的执行速度

2、数组的不足

  • 插入与删除效率低:当数组中元素较多时,插入与删除操作需要移动大量的元素。
  • 长度不可变:数组在初始化后长度就固定了,扩容数组需要将所有数据复制到新数组,开销很大。
  • 空间浪费:如果数组分配的大小超过实际所需,那么多余的空间就被浪费了。

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

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

相关文章

YoloV10改进策略:卷积篇|基于PConv的二次创新|附结构图|性能和精度得到大幅度提高(独家原创)

文章目录 摘要论文指导PConv在论文中的描述改进YoloV10的描述改进代码与结构图改进方法测试结果总结摘要 在PConv的基础上做了二次创新,创新后的模型不仅在精度和速度上有了质的提升,还可以支持Stride为2的降采样。 改进方法简单高效,需要发论文的同学不要错过! 论文指导…

机器学习实战篇——肿瘤良性/恶性分类器(二元逻辑回归)

机器学习之实战篇——肿瘤良性/恶性分类器(二元逻辑回归) 前言数据集和实验文件下载相关文章推荐实验过程导入相关模块数据预处理手写二元逻辑回归模型(小批量梯度下降)sklearn逻辑回归器 前言 实验中难免有许多缺陷和错误&#…

Mac M1安装Hive

一、下载解压Hive 1.官网地址 https://dlcdn.apache.org/hive/ 2.选择对应版本进行下载,这里我以3.1.3为例; 3.下载好后,进行解压,并重命名为hive-3.1.3,放到资源库目录下; 二、配置系统环境 1.打开~/…

Hack The Box-Infiltrator【更新中】

信息收集&端口利用 nmap -sSVC infiltrator.htbStarting Nmap 7.94SVN ( https://nmap.org ) at 2024-09-02 09:17 CST Nmap scan report for infiltrator.htb Host is up (0.61s latency). Not shown: 987 filtered tcp ports (no-response) PORT STATE SERVICE …

C++竞赛初阶L1-15-第六单元-多维数组(34~35课)551: T456501 计算矩阵边缘元素之和

题目内容 输入一个整数矩阵,计算位于矩阵边缘的元素之和。 所谓矩阵边缘的元素,就是第一行和最后一行的元素以及第一列和最后一列的元素。 输入格式 第 1 行包含两个整数,分别为行数 m 和列数 n,两个整数之间空格隔开。 第 2 …

【单调栈 】2289. 使数组按非递减顺序排列

本文涉及的基础知识点 单调栈分类、封装和总结 LeetCode2289. 使数组按非递减顺序排列 给你一个下标从 0 开始的整数数组 nums 。在一步操作中&#xff0c;移除所有满足 nums[i - 1] > nums[i] 的 nums[i] &#xff0c;其中 0 < i < nums.length 。 重复执行步骤&a…

Sobel算子,Scharr算子和Laplacian算子

图像边缘检测大幅度地减少了数据量&#xff0c;并且剔除了可以认为不相关的信息&#xff0c;保留了图像重要的结构属性。有许多方法用于边缘检测&#xff0c; 绝大部分可以划分为两类&#xff1a;基于搜索和基于零穿越。 基于搜索:通过寻找图像一阶导数中的最大值来检测边界&am…

4.1 数据分析-excel 基本操作

第四节&#xff1a;数据分析-excel 基本操作 课程目标 学会excel 基本操作 课程内容 数据伪造 产生一份招聘数据 import pandas as pd from faker import Faker import random import numpy as np# 创建一个Faker实例&#xff0c;用于生成假数据&#xff0c;指定中文本地…

c# 笔记 winform添加右键菜单,获取文件大小 ,多条件排序OrderBy、ThenBy,list<double>截取前5个

Winform右键菜单‌ 要在C# Winform应用程序中添加右键菜单&#xff0c;‌你可以按照以下步骤操作&#xff1a;‌ 1.‌创建菜单项‌ 在Form的构造函数或加载事件中&#xff0c;‌创建ContextMenuStrip控件的实例&#xff0c;‌并为其添加菜单项。‌ 2.‌绑定到控件‌ 将Con…

踩坑记录(序列化与反序列化)

问题描述 实体类中设定字段名称为 sValue和yValue 返回给前段后,变成了svalue,yvalue 字段设置 测试结果:与字段不符,匹配失败 解决方法 在字段上添加JsonProperty("字段名")注解

报告 | 以消费者为中心,消费品零售行业数字化建设持续深化

​2024年是“消费促进年”&#xff0c;国内消费市场稳步复苏。在消费需求多样化、国家政策的推动下&#xff0c;“数字化转型”仍是消费品零售行业的年度主题词&#xff0c;是品牌方获取核心竞争力的必要途径。消费品零售行业的数字化转型重心有所调整&#xff0c;从线上渠道布…

虚拟系统VS

定义 虚拟系统VS&#xff08;Virtual System&#xff09;是指将一台物理设备PS&#xff08;Physical System&#xff09;虚拟成多个相互隔离的逻辑系统。每个VS独立工作&#xff0c;在业务功能上等同于一台独立的传统物理设备&#xff0c;如图2-1所示。 目的 随着网络规模的不…

macos OneNote 2016 for Mac 官方pkg下载地址 - macos 10.15 Catalion 可用Onenote版本官方下载地址

macos 10.15 Catalion 版本的系统已经无法正常从应用商店下载到可用的Onenote 应用,原因是版本不受支持, 而且onenote官方链接的应用商店地址https://apps.apple.com/us/app/microsoft-onenote/id784801555?mt12在中国地区也无法访问, 所以中国地区用户如果想使用onenote应用…

C语言 | Leetcode C语言题解之第394题字符串解码

题目&#xff1a; 题解&#xff1a; #define N 2000typedef struct {int data[30];;int top; } Stack;void push(Stack *s, int e) { s->data[(s->top)] e; }int pop(Stack *s) { return s->data[--(s->top)]; }//多位数字串转换成int int strToInt(char *s) {cha…

Charles抓包全流程(Mac端+iOS端)

文章目录 与其他抓包软件的对比FiddlerWireShark Charles下载安装及配置Charles抓包实践小结 Charles Proxy是一个广泛使用的网络调试代理工具&#xff0c;它允许开发者监控和分析所有经过计算机的HTTP和SSL/HTTPS网络流量信息。 与其他抓包软件的对比 Fiddler Charles 支持多…

Leetcode3250. 单调数组对的数目 I

Every day a Leetcode 题目来源&#xff1a;3250. 单调数组对的数目 I 解法1&#xff1a;记忆化搜索 题目输入一个数组nums。 假设有两个数组A和B&#xff0c;A递增&#xff0c;B递减&#xff0c;且 Ai Bi numsi ​ 问有多少对(A,B)数组对。 解法&#xff1a; 代码&…

自动回复的客服系统-支持关键词回复或AI智能回复

用户咨询量很大的时候&#xff0c;迫切需要一个自动回复的工具 对于公域流量&#xff0c;非常推荐大家使用网页版在线客服系统&#xff0c;与访客沟通。 既能实现自动回复&#xff0c;又能人工后台即时回复 \/x : llike620

Redis集群搭建以及用idea连接集群

一、redis的集群搭建&#xff1a; 判断一个是集群中的节点是否可用,是集群中的所用主节点选举过程,如果半数以上的节点认为当前节点挂掉,那么当前节点就是挂掉了,所以搭建redis集群时建议节点数最好为奇数&#xff0c;搭建集群至少需要三个主节点,三个从节点,至少需要6个节点。…

Qt/C++百度地图/高德地图/天地图/腾讯地图/谷歌地图/加载绘图工具栏

一、前言说明 在地图中提供一个绘图工具栏&#xff0c;可以便捷的在地图上添加各种覆盖物&#xff0c;比如折线、多边形、矩形、圆形等&#xff0c;然后可以获取这些覆盖物的路径以及中心点等属性。这里有几个小插曲&#xff0c;比如百度地图gl版本默认不提供这个功能&#xf…

TPH-YOLOv5:基于Transformer预测头的改进YOLOv5,用于无人机捕获场景的目标检测

摘要 提出了TPH-YOLOv5。在YOLOv5的基础上&#xff0c;增加了一个预测头来检测不同尺度的目标。然后用Transformer Prediction Heads&#xff08;TPH&#xff09;代替原有的预测头&#xff0c;探索自注意机制的预测潜力。还集成了卷积块注意力模型&#xff08;CBAM&#xff09;…