Skip to content

implementation

文件信息

  • 📄 原文件:implementation.py
  • 🔤 语言:python

动态数组实现 从零实现一个动态数组,理解底层原理。

完整代码

python
from typing import TypeVar, Generic, Iterator, Optional
import ctypes

T = TypeVar('T')


class DynamicArray(Generic[T]):
    """
    动态数组实现

    特性:
    - 自动扩容/缩容
    - 支持负索引
    - 支持迭代
    - 泛型支持
    """

    def __init__(self, capacity: int = 10):
        """
        初始化动态数组

        Args:
            capacity: 初始容量
        """
        self._size = 0                    # 实际元素数量
        self._capacity = capacity          # 当前容量
        self._array = self._make_array(capacity)  # 底层数组

    def _make_array(self, capacity: int):
        """创建底层数组(模拟C数组)"""
        return (capacity * ctypes.py_object)()

    # ==================== 基本操作 ====================

    def __len__(self) -> int:
        """返回元素数量"""
        return self._size

    def __getitem__(self, index: int) -> T:
        """
        获取元素(支持负索引)

        时间复杂度: O(1)
        """
        index = self._validate_index(index)
        return self._array[index]

    def __setitem__(self, index: int, value: T) -> None:
        """
        设置元素

        时间复杂度: O(1)
        """
        index = self._validate_index(index)
        self._array[index] = value

    def _validate_index(self, index: int) -> int:
        """验证并转换索引"""
        if index < 0:
            index += self._size
        if not 0 <= index < self._size:
            raise IndexError(f"索引 {index} 超出范围 [0, {self._size})")
        return index

    # ==================== 添加操作 ====================

    def append(self, value: T) -> None:
        """
        在末尾添加元素

        时间复杂度: 均摊 O(1)
        """
        if self._size == self._capacity:
            self._resize(2 * self._capacity)  # 扩容 2 倍

        self._array[self._size] = value
        self._size += 1

    def insert(self, index: int, value: T) -> None:
        """
        在指定位置插入元素

        时间复杂度: O(n)

        Args:
            index: 插入位置
            value: 插入的值
        """
        # 允许在末尾插入
        if index < 0:
            index += self._size
        if not 0 <= index <= self._size:
            raise IndexError(f"插入位置 {index} 无效")

        if self._size == self._capacity:
            self._resize(2 * self._capacity)

        # 后移元素:从后往前移动
        for i in range(self._size, index, -1):
            self._array[i] = self._array[i - 1]

        self._array[index] = value
        self._size += 1

    def extend(self, iterable) -> None:
        """添加多个元素"""
        for item in iterable:
            self.append(item)

    # ==================== 删除操作 ====================

    def pop(self, index: int = -1) -> T:
        """
        删除并返回指定位置的元素

        时间复杂度:
            - 末尾: O(1)
            - 其他位置: O(n)
        """
        index = self._validate_index(index)
        value = self._array[index]

        # 前移元素
        for i in range(index, self._size - 1):
            self._array[i] = self._array[i + 1]

        self._size -= 1
        self._array[self._size] = None  # 帮助垃圾回收

        # 缩容:当元素数量少于容量的 1/4 时
        if self._size > 0 and self._size <= self._capacity // 4:
            self._resize(self._capacity // 2)

        return value

    def remove(self, value: T) -> None:
        """
        删除第一个匹配的元素

        时间复杂度: O(n)
        """
        for i in range(self._size):
            if self._array[i] == value:
                self.pop(i)
                return
        raise ValueError(f"{value} 不在数组中")

    def clear(self) -> None:
        """清空数组"""
        self._size = 0
        self._capacity = 10
        self._array = self._make_array(self._capacity)

    # ==================== 查找操作 ====================

    def index(self, value: T) -> int:
        """
        查找元素的索引

        时间复杂度: O(n)
        """
        for i in range(self._size):
            if self._array[i] == value:
                return i
        raise ValueError(f"{value} 不在数组中")

    def count(self, value: T) -> int:
        """统计元素出现次数"""
        return sum(1 for i in range(self._size) if self._array[i] == value)

    def __contains__(self, value: T) -> bool:
        """检查元素是否存在"""
        for i in range(self._size):
            if self._array[i] == value:
                return True
        return False

    # ==================== 内部方法 ====================

    def _resize(self, new_capacity: int) -> None:
        """
        调整容量

        时间复杂度: O(n)
        """
        new_array = self._make_array(new_capacity)
        for i in range(self._size):
            new_array[i] = self._array[i]
        self._array = new_array
        self._capacity = new_capacity

    # ==================== 迭代器 ====================

    def __iter__(self) -> Iterator[T]:
        """支持 for 循环"""
        for i in range(self._size):
            yield self._array[i]

    def __reversed__(self) -> Iterator[T]:
        """支持反向迭代"""
        for i in range(self._size - 1, -1, -1):
            yield self._array[i]

    # ==================== 其他方法 ====================

    def __repr__(self) -> str:
        """字符串表示"""
        items = [str(self._array[i]) for i in range(self._size)]
        return f"DynamicArray([{', '.join(items)}])"

    def __eq__(self, other) -> bool:
        """判断相等"""
        if not isinstance(other, DynamicArray):
            return False
        if len(self) != len(other):
            return False
        for i in range(self._size):
            if self._array[i] != other._array[i]:
                return False
        return True

    @property
    def capacity(self) -> int:
        """返回当前容量"""
        return self._capacity

    def is_empty(self) -> bool:
        """检查是否为空"""
        return self._size == 0


# ============================================================
#                    常用数组算法
# ============================================================

def binary_search(arr: list, target) -> int:
    """
    二分查找(要求有序数组)

    时间复杂度: O(log n)
    空间复杂度: O(1)

    Returns:
        找到返回索引,否则返回 -1
    """
    left, right = 0, len(arr) - 1

    while left <= right:
        mid = left + (right - left) // 2  # 防止溢出

        if arr[mid] == target:
            return mid
        elif arr[mid] < target:
            left = mid + 1
        else:
            right = mid - 1

    return -1


def two_sum(arr: list, target: int) -> tuple:
    """
    两数之和

    时间复杂度: O(n)
    空间复杂度: O(n)

    Returns:
        返回两个数的索引,如 (0, 2)
    """
    seen = {}  # 值 -> 索引

    for i, num in enumerate(arr):
        complement = target - num
        if complement in seen:
            return (seen[complement], i)
        seen[num] = i

    return (-1, -1)


def remove_duplicates(arr: list) -> int:
    """
    原地删除排序数组中的重复项

    时间复杂度: O(n)
    空间复杂度: O(1)

    Returns:
        不重复元素的数量
    """
    if not arr:
        return 0

    # 双指针:slow 指向不重复区域的末尾
    slow = 0

    for fast in range(1, len(arr)):
        if arr[fast] != arr[slow]:
            slow += 1
            arr[slow] = arr[fast]

    return slow + 1


def rotate_array(arr: list, k: int) -> None:
    """
    旋转数组(向右移动 k 步)

    方法:三次反转
    [1,2,3,4,5,6,7] k=3
    -> [7,6,5,4,3,2,1] 全部反转
    -> [5,6,7,4,3,2,1] 反转前 k 个
    -> [5,6,7,1,2,3,4] 反转后 n-k 个

    时间复杂度: O(n)
    空间复杂度: O(1)
    """
    n = len(arr)
    k = k % n  # 处理 k > n 的情况

    def reverse(left: int, right: int):
        while left < right:
            arr[left], arr[right] = arr[right], arr[left]
            left += 1
            right -= 1

    reverse(0, n - 1)      # 全部反转
    reverse(0, k - 1)      # 反转前 k 个
    reverse(k, n - 1)      # 反转后 n-k 个


def max_subarray(arr: list) -> int:
    """
    最大子数组和(Kadane 算法)

    时间复杂度: O(n)
    空间复杂度: O(1)
    """
    if not arr:
        return 0

    max_sum = current_sum = arr[0]

    for num in arr[1:]:
        # 要么加入当前子数组,要么从当前位置重新开始
        current_sum = max(num, current_sum + num)
        max_sum = max(max_sum, current_sum)

    return max_sum


def merge_sorted_arrays(arr1: list, m: int, arr2: list, n: int) -> None:
    """
    合并两个有序数组(arr1 有足够空间)

    方法:逆向双指针,从后往前填充

    时间复杂度: O(m + n)
    空间复杂度: O(1)
    """
    p1 = m - 1  # arr1 的指针
    p2 = n - 1  # arr2 的指针
    p = m + n - 1  # 合并后的指针

    while p2 >= 0:
        if p1 >= 0 and arr1[p1] > arr2[p2]:
            arr1[p] = arr1[p1]
            p1 -= 1
        else:
            arr1[p] = arr2[p2]
            p2 -= 1
        p -= 1


# ============================================================
#                    测试代码
# ============================================================

if __name__ == "__main__":
    print("=" * 60)
    print("动态数组测试")
    print("=" * 60)

    # 基本操作测试
    arr = DynamicArray()

    print("\n--- 添加元素 ---")
    for i in range(1, 6):
        arr.append(i * 10)
    print(f"添加后: {arr}")
    print(f"长度: {len(arr)}, 容量: {arr.capacity}")

    print("\n--- 插入元素 ---")
    arr.insert(2, 99)
    print(f"在索引2插入99: {arr}")

    print("\n--- 访问元素 ---")
    print(f"arr[0] = {arr[0]}")
    print(f"arr[-1] = {arr[-1]}")

    print("\n--- 删除元素 ---")
    popped = arr.pop()
    print(f"pop(): {popped}, 数组: {arr}")
    popped = arr.pop(0)
    print(f"pop(0): {popped}, 数组: {arr}")

    print("\n--- 迭代 ---")
    print("正向:", list(arr))
    print("反向:", list(reversed(arr)))

    print("\n--- 查找 ---")
    print(f"99 in arr: {99 in arr}")
    print(f"index(99): {arr.index(99)}")

    print("\n" + "=" * 60)
    print("算法测试")
    print("=" * 60)

    print("\n--- 二分查找 ---")
    sorted_arr = [1, 3, 5, 7, 9, 11, 13]
    print(f"数组: {sorted_arr}")
    print(f"查找 7: 索引 {binary_search(sorted_arr, 7)}")
    print(f"查找 4: 索引 {binary_search(sorted_arr, 4)}")

    print("\n--- 两数之和 ---")
    nums = [2, 7, 11, 15]
    target = 9
    print(f"数组: {nums}, 目标: {target}")
    print(f"结果: {two_sum(nums, target)}")

    print("\n--- 删除重复项 ---")
    nums = [1, 1, 2, 2, 3, 4, 4, 5]
    print(f"原数组: {nums}")
    new_len = remove_duplicates(nums)
    print(f"去重后: {nums[:new_len]}")

    print("\n--- 旋转数组 ---")
    nums = [1, 2, 3, 4, 5, 6, 7]
    print(f"原数组: {nums}")
    rotate_array(nums, 3)
    print(f"右移3位: {nums}")

    print("\n--- 最大子数组和 ---")
    nums = [-2, 1, -3, 4, -1, 2, 1, -5, 4]
    print(f"数组: {nums}")
    print(f"最大子数组和: {max_subarray(nums)}")

    print("\n--- 合并有序数组 ---")
    arr1 = [1, 3, 5, 0, 0, 0]
    arr2 = [2, 4, 6]
    print(f"arr1: {arr1[:3]}, arr2: {arr2}")
    merge_sorted_arrays(arr1, 3, arr2, 3)
    print(f"合并后: {arr1}")

💬 讨论

使用 GitHub 账号登录后即可参与讨论

基于 MIT 许可发布