可变数组的底层实现是基于静态数组的,通过动态申请内存空间、重新分配内存空间等方式来实现可变长度。
当可变数组的扩容通常是在数组元素个数到达容量上限时进行。
具体实现方式: 重新申请一块更大的内存空间,将原数组的元素拷贝到新的内存空间中,并释放原内存空间。
Python list
扩容的主要过程和实现方式:
初始化:当创建一个空列表时,Python会分配一个最小的初始容量(例如0或者某个小的默认值)。
添加元素:当列表需要添加元素且当前容量不足时,Python会进行扩容。
扩容策略:Python使用一种几何级数的扩容策略。通常是将当前容量扩大为原来的1.5倍或2倍。这种策略能够在均摊情况下将每次添加操作的时间复杂度保持在O(1)。
内存复制:扩容时,Python会分配一块新的、更大的内存空间,并将旧数组中的元素复制到新的内存空间中。
import sys
# 创建一个空列表
my_list = []
# 打印列表的容量和长度
print(f"初始容量: {sys.getsizeof(my_list)}, 长度: {len(my_list)}")
# 向列表中添加元素,并打印扩容后的容量和长度
for i in range(20):
my_list.append(i)
print(f"添加元素 {i} 后,容量: {sys.getsizeof(my_list)}, 长度: {len(my_list)}")
Python中常见的可变数组
list
(列表):最常用的可变数组类型。
支持各种元素类型,可以动态扩容。
适合大多数通用用途的场景。
deque
(双端队列):位于
collections
模块中。支持在两端快速添加和删除元素,适合需要频繁在两端操作的场景。
内部实现为双向链表,具有O(1)时间复杂度的append和pop操作。
from collections import deque
dq = deque([1, 2, 3])
dq.append(4) # 在右端添加元素
dq.appendleft(0) # 在左端添加元素
dq.pop() # 删除右端元素
dq.popleft() # 删除左端元素
array
(数组):位于
array
模块中。只能存储同类型的元素,比
list
更加节省内存。提供基本的数组操作,适合需要固定类型、节省内存的场景。
import array
arr = array.array('i', [1, 2, 3]) # 创建一个整数类型的数组
arr.append(4)
arr.extend([5, 6])
bytearray
(字节数组):用于处理二进制数据。
支持类似列表的操作,可以动态扩展。
适合处理字节数据和二进制文件的场景。
ba = bytearray(b'hello')
ba.append(33) # 添加一个字节
ba.extend(b' world')
numpy.ndarray
(NumPy数组):位于第三方库
NumPy
中。
支持多维数组和大量的数值计算操作。
适合需要高性能数值计算和矩阵运算的场景。
import numpy as np
np_arr = np.array([1, 2, 3, 4])
np_arr = np.append(np_arr, [5, 6])
string
(字符串):虽然字符串本身是不可变的,但通过将其转换为
list
或bytearray
可以实现可变操作。
s = "hello"
s_list = list(s) # 转换为列表以进行可变操作
s_list.append('!')
result = ''.join(s_list) # 转换回字符串