原生 Python 中其实没有数组的概念,而是使用了类似 Java 中的 ArrayList 容器类数据结构,叫做列表。通常我们把列表来作为 Python 中的数组使用。Python 中列表存储的数据类型可以不一致,数组长度也可以不一致。例如:
arr = ['python', 'java', ['asp', 'php'], 'c']
- 数组的基本操作 # 数据结构的操作一般涉及到增、删、改、查 4 种情况,下面我们一起来看一下数组的基本操作。
2.1 访问元素 # 访问数组中第 i 个元素:只需要检查 i 的范围是否在合法的范围区间,即 0 <= i <= len(nums) - 1。超出范围的访问为非法访问。当位置合法时,由给定下标得到元素的值。访问操作不依赖于数组中元素个数,因此时间复杂度为 。
示例代码如下:
def value(nums, i): if 0 <= i <= len(nums) - 1: print(nums[i])
arr = [0, 5, 2, 3, 7, 1, 6] value(arr, 3) 2.2 查找元素 # 查找数组中元素值为 val 的位置:在数组无序的情况下,只能通过将 val 与数组中的数据元素逐一对比的方式进行检索,也称为线性查找。建立一个基于下标的循环,每次将val 与当前数据元素 nums[i] 进行比较。在找到元素的时候返回元素下标,找不到时可以返回一个特殊值(例如 -1)。线性查找操作依赖于数组中元素个数,因此时间复杂度为 。
示例代码如下 :
def find(nums, val): for i in range(len(nums)): if nums[i] == val: return i return -1
arr = [0, 5, 2, 3, 7, 1, 6] print(find(arr, 5)) 2.3 插入元素 # 插入元素操作分为两种:「在数组尾部插入值为 val 的元素」和「在数组第 i 个位置上插入值为 val 的元素」。
在数组尾部插入值为 val 的元素:如果数组尾部容量不满,则直接把 val 放在数组尾部的空闲位置,并更新数组的元素计数值。如果数组容量满了,则插入失败。不过,Python 中的 list 做了其他处理,当数组容量满了,则会开辟新的空间进行插入。在尾部插入元素的操作不依赖数组个数,其时间复杂度为 。
Python 中的 list 直接封装了尾部插入操作,直接调用 append 方法即可。
插入元素
示例代码如下:
arr = [0, 5, 2, 3, 7, 1, 6] val = 4 arr.append(val) print(arr) 在数组第 i 个位置上插入值为 val 的元素:先检查插入下标 i 是否合法,即 0 <= i <= len(nums)。确定合法位置后,通常情况下第 i 个位置上已经有数据了(除非 i == len(nums) ),要把第 i 个位置到第 len(nums) - 1 位置上的元素依次向后移动,然后再在第 i 个元素位置插入 val 值,并更新数组的元素计数值。因为移动元素的操作次数跟元素个数有关,最坏和平均时间复杂度都是 。
Python 中的 list 直接封装了中间插入操作,直接调用 insert 方法即可。
插入中间元素
示例代码如下:
arr = [0, 5, 2, 3, 7, 1, 6] i, val = 2, 4 arr.insert(i, val) print(arr) 2.4 改变元素 # 将数组中第 i 个元素值改为 val:改变元素操作跟访问元素操作类似。需要先检查 i 的范围是否在合法的范围区间,即 0 <= i <= len(nums) - 1。然后将第 i 个元素值赋值为 val。访问操作不依赖于数组中元素个数,因此时间复杂度为 。
改变元素
示例代码如下:
def change(nums, i, val): if 0 <= i <= len(nums) - 1: nums[i] = val
arr = [0, 5, 2, 3, 7, 1, 6] i, val = 2, 4 change(arr, i, val) print(arr) 2.5 删除元素 # 删除元素分为三种情况:「删除数组尾部元素」、「删除数组第 i 个位置上的元素」、「基于条件删除元素」。
删除数组尾部元素:只需将元素计数值减一即可。这样原来的数组尾部元素不再位于合法的数组下标范围,就相当于删除了。时间复杂度为 。
Python 中的 list 直接封装了删除数组尾部元素的操作,只需要调用 pop 方法即可。
删除尾部元素
示例代码如下:
arr = [0, 5, 2, 3, 7, 1, 6] arr.pop() print(arr) 删除数组第 i 个位置上的元素:先检查下标 i 是否合法,即 o <= i <= len(nums) - 1。如果下标合法,则将第 i + 1 个位置到第 len(nums) - 1 位置上的元素依次向左移动。删除后修改数组的元素计数值。删除中间位置元素的操作同样涉及移动元素,而移动元素的操作次数跟元素个数有关,因此删除中间元素的最坏和平均时间复杂度都是 。
Python 中的 list 直接封装了删除数组中间元素的操作,只需要以下标作为参数调用 pop 方法即可。
删除中间元素
示例代码如下:
arr = [0, 5, 2, 3, 7, 1, 6] i = 3 arr.pop(i) print(arr) 基于条件删除元素:这种操作一般不给定被删元素的位置,而是给出一个条件要求删除满足这个条件的(一个、多个或所有)元素。这类操作也是通过循环检查元素,查找到元素后将其删除。删除多个元素操作中涉及到的多次移动元素操作,可以通过算法改进,将多趟移动元素操作转变为一趟移动元素,从而将时间复杂度降低为 。一般而言,这类删除操作都是线性时间操作,时间复杂度为 。
示例代码如下:
arr = [0, 5, 2, 3, 7, 1, 6] i = 3 arr.remove(5) print(arr) 到这里,有关数组的基础知识就介绍完了。下面进行一下总结。
- 数组总结 # 数组是最基础、最简单的数据结构。数组是实现线性表的顺序结构存储的基础。它使用一组连续的内存空间,来存储一组具有相同类型的数据。
数组的最大特点的支持随机访问。其访问元素、改变元素的时间复杂度为 ,在尾部插入、删除元素的时间复杂度也是 ,普通情况下插入、删除元素的时间复杂度为 。