🔴 Сложный ⏱️ 25 минут

Массивы и списки: основа структур данных

Массивы и списки: основа структур данных

🎯 Зачем это нужно?

Представь, что ты создаёшь Instagram 📱. Как хранить все фотографии пользователя? Или YouTube - как управлять плейлистом из тысяч видео? А Netflix - как быстро найти фильм среди миллионов? Все эти задачи решают массивы и списки - самые базовые, но критически важные структуры данных!

💼 В реальной разработке:

  • Google использует массивы для хранения результатов поиска
  • Spotify хранит треки в плейлистах как списки
  • Игры вроде Fortnite используют массивы для координат игроков

📚 История вопроса

Концепция массива появилась ещё в 1940-х с первыми компьютерами! Джон фон Нейман понял: чтобы программа была эффективной, данные нужно организовывать в памяти структурированно. Интересный факт: в языке FORTRAN (1957) массивы были ЕДИНСТВЕННОЙ структурой данных! 🤯

💡 Интуиция

Массив - это как шкафчики в школьной раздевалке 🏫. Каждый шкафчик имеет номер (индекс), и в каждом лежит одна вещь. Хочешь взять куртку из 15-го шкафчика? Идёшь прямо к нему - это O(1) операция!

Список - больше похож на поезд 🚂. Вагоны соединены цепочкой, чтобы добраться до 10-го вагона, нужно пройти через первые 9. Зато можно легко добавить новый вагон в любое место!

[МЕДИА: image_01] Описание: Сравнение массива (шкафчики с номерами) и связанного списка (вагоны поезда) Промпт: “educational illustration comparing array as numbered lockers vs linked list as train cars, modern flat design, tech colors blue and orange, clear indexing numbers, arrows showing connections”

📐 Формальное определение

Массив - структура данных, хранящая элементы одного типа в непрерывном блоке памяти. Доступ к элементу по индексу i: A[i] = base_address + i × element_size

Связанный список - структура данных из узлов, где каждый узел содержит данные и указатель на следующий элемент.

# Массив в Python (список с фиксированным размером)
import array
arr = array.array('i', [1, 2, 3, 4, 5])  # O(1) доступ
print(arr[2])  # Мгновенно получаем 3

# Связанный список (упрощённая реализация)
class Node:
    def __init__(self, data):
        self.data = data
        self.next = None

class LinkedList:
    def __init__(self):
        self.head = None
    
    def append(self, data):  # O(n)
        new_node = Node(data)
        if not self.head:
            self.head = new_node
            return
        current = self.head
        while current.next:
            current = current.next
        current.next = new_node

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

Операция Массив Связанный список
Доступ по индексу O(1) O(n)
Вставка в начало O(n) O(1)
Вставка в конец O(1)* O(n)
Удаление O(n) O(1)**
Поиск O(n) O(n)

*при наличии места, иначе O(n) **при известном узле

[МЕДИА: image_02] Описание: Таблица сложности операций с визуализацией Big O Промпт: “complexity comparison table for arrays vs linked lists, Big O notation, colorful performance indicators, green for O(1), yellow for O(n), modern data visualization style”

🔍 Примеры с разбором

Пример 1: Поиск максимального элемента

def find_max(arr):
    """Находит максимальный элемент в массиве"""
    if not arr:
        return None
    
    max_val = arr[0]  # Предполагаем, что первый максимальный
    for i in range(1, len(arr)):
        if arr[i] > max_val:
            max_val = arr[i]
    return max_val

# Тестируем
scores = [85, 92, 78, 96, 88]  # Оценки студентов
print(find_max(scores))  # 96

Сложность: O(n) - нужно просмотреть каждый элемент Память: O(1) - используем только одну переменную max_val

Пример 2: Реверс связанного списка

def reverse_linked_list(head):
    """Разворачивает связанный список"""
    prev = None
    current = head
    
    while current:
        next_temp = current.next  # Сохраняем следующий
        current.next = prev       # Разворачиваем связь
        prev = current           # Двигаем prev
        current = next_temp      # Двигаем current
    
    return prev  # prev теперь новая голова

Визуализация:

До:  1 → 2 → 3 → 4 → None
После: None ← 1 ← 2 ← 3 ← 4

[МЕДИА: animation_01] Описание: Анимация реверса связанного списка по шагам Промпт: “step-by-step animation of linked list reversal, nodes with arrows changing direction, highlighting prev and current pointers, educational programming visualization”

Пример 3: Двумерный массив (матрица)

# Создание матрицы 3x3 для крестиков-ноликов
board = [[' ' for _ in range(3)] for _ in range(3)]

def make_move(board, row, col, player):
    """Делает ход в крестики-нолики"""
    if board[row][col] == ' ':
        board[row][col] = player
        return True
    return False

def print_board(board):
    """Выводит доску на экран"""
    for row in board:
        print(' | '.join(row))
        print('-+-+-')

# Тестируем
make_move(board, 1, 1, 'X')  # X в центр
print_board(board)

🎮 Практика

Базовый уровень 🟢

Задание 1: Напиши функцию, которая находит все чётные числа в массиве

def find_even(arr):
    # Твой код здесь
    pass

# Тест: find_even([1, 2, 3, 4, 5, 6]) должно вернуть [2, 4, 6]

Задание 2: Реализуй функцию сдвига массива влево на k позиций

def rotate_left(arr, k):
    # [1,2,3,4,5] при k=2 → [3,4,5,1,2]
    pass

Задание 3: Найди второй максимальный элемент в массиве

def second_max(arr):
    # Не используй сортировку!
    pass

Задание 4: Проверь, является ли массив палиндромом

def is_palindrome(arr):
    # [1,2,3,2,1] → True
    # [1,2,3,4] → False
    pass

Продвинутый уровень 🟡

Задание 5: Merge Sort для массивов - реализуй алгоритм слияния

def merge_sort(arr):
    """Сортировка слиянием O(n log n)"""
    # Разделяй и властвуй!
    pass

Задание 6: Реализуй стек используя связанный список

class Stack:
    def __init__(self):
        self.top = None
    
    def push(self, data):
        pass
    
    def pop(self):
        pass
    
    def peek(self):
        pass

Задание 7: Найди пересечение двух отсортированных массивов

def intersection(arr1, arr2):
    # [1,2,2,3] и [2,2,3,4] → [2,2,3]
    # Используй два указателя!
    pass

Задание 8: Циклический связанный список - детектор цикла

def has_cycle(head):
    """Алгоритм Floyd's Cycle Detection (черепаха и заяц)"""
    pass

Челлендж 🔴

Задание 9: Максимальная сумма подмассива (Kadane’s Algorithm)

def max_subarray_sum(arr):
    """
    Найди подмассив с максимальной суммой
    [-2,1,-3,4,-1,2,1,-5,4] → подмассив [4,-1,2,1] сумма = 6
    """
    pass

Задание 10: LRU Cache используя связанный список + хэш-таблица

class LRUCache:
    def __init__(self, capacity):
        self.capacity = capacity
        # Твоя реализация
    
    def get(self, key):
        pass
    
    def put(self, key, value):
        pass

⚠️ Частые ошибки

Ошибка: Выход за границы массива (IndexError)

arr = [1, 2, 3]
print(arr[5])  # Ошибка!

Правильно: Всегда проверяй границы

if 0 <= index < len(arr):
    print(arr[index])

💡 Почему: Python не предотвращает выход за границы, нужно следить самому

Ошибка: Путаница в указателях при работе со списками

# Потеря ссылки на голову
head = head.next  # Потеряли первый элемент!

Правильно: Сохраняй ссылки перед изменением

temp = head.next
# работаем с temp
head = temp

💡 Почему: В связанных списках легко потерять узлы без сборки мусора

Ошибка: Изменение списка во время итерации

arr = [1, 2, 3, 4, 5]
for item in arr:
    arr.remove(item)  # Может пропустить элементы!

Правильно: Итерируй по копии или в обратном порядке

for item in arr[:]:  # По копии
    arr.remove(item)

🎓 Главное запомнить

Массив = быстрый доступ O(1), но фиксированный размер ✅ Связанный список = динамический размер, но медленный доступ O(n)
Индексация начинается с 0 в большинстве языков ✅ Big O помогает сравнивать эффективность операций

🔗 Связь с другими темами

Массивы и списки - это фундамент для:

  • Стеков и очередей (урок 253) - специализированные списки
  • Хэш-таблиц (урок 254) - массивы + хэширование
  • Деревьев (урок 255) - узлы связанного списка с несколькими детьми
  • Графов (урок 256) - списки смежности для представления связей
  • Сортировки (урок 257) - все алгоритмы работают с массивами

Понял тему? Закрепи в боте! 🚀

Попрактикуйся на задачах и получи персональные рекомендации от AI

💪 Начать тренировку
💬 Есть вопрос? Спроси бота!