Назад к вопросам
Middle+
68
questionbank

Как бы вы реализовали структуру данных, аналогичную списку (list) в Python, если бы её не существовало?

Sobes Copilot

Получайте ответы в реальном времени

Ответ от нейросети

sobes.tech AI

Я бы реализовал её на основе динамического массива.

Основные принципы:

  1. Использование массива фиксированного размера для хранения элементов.
  2. При достижении предела емкости массива, создание нового массива большего размера (как правило, в 1.5 - 2 раза больше) и копирование туда всех элементов.
  3. Хранение текущего количества элементов.
  4. Предоставление методов для добавления, удаления, доступа по индексу, итерирования и определения длины.

Пример базовой структуры:

class MyList:
    def __init__(self, capacity=10):
        self._capacity = capacity # Максимальная вместимость
        self._size = 0           # Текущее количество элементов
        self._array = [None] * self._capacity # Внутренний массив

    def _resize(self, new_capacity):
        new_array = [None] * new_capacity
        for i in range(self._size):
            new_array[i] = self._array[i]
        self._array = new_array
        self._capacity = new_capacity

    def append(self, item):
        if self._size == self._capacity:
            self._resize(self._capacity * 2) # Увеличиваем размер в 2 раза
        self._array[self._size] = item
        self._size += 1

    def __len__(self):
        return self._size

    def __getitem__(self, index):
        if 0 <= index < self._size:
            return self._array[index]
        raise IndexError("index out of range")

    def __setitem__(self, index, item):
        if 0 <= index < self._size:
            self._array[index] = item
        else:
            raise IndexError("index out of range")

    def __iter__(self):
        for i in range(self._size):
            yield self._array[i]

    # Добавление других методов: insert, pop, remove, index и т.д.

Преимущества такого подхода:

  • Доступ по индексу (get/set) за O(1) в среднем.
  • Быстрое добавление в конец (append) за O(1) в среднем (из-за амортизированной стоимости перевыделения памяти).
  • Итерирование за O(n), где n — количество элементов.

Сложности и компромиссы:

  • Вставка или удаление из середины требует сдвига элементов, что занимает O(n) времени.
  • Перевыделение памяти и копирование могут быть дорогими операциями, но происходят редко и распределяются по многим операциям добавления (амортизированный анализ).

Для полной аналогии с list потребуется реализовать множество других методов (insert, pop, remove, index, срезы и т.д.), сохраняя эффективность стандартных операций.