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

Стеки и очереди: структуры данных в действии

Стеки и очереди: структуры данных в действии

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

Представь, что ты заходишь в переполненный лифт 🛗. Кто выходит первым? Правильно - тот, кто зашёл последним! А теперь представь очередь в столовую 🍽️ - кто получает еду первым? Тот, кто встал в очередь раньше всех.

Эти простые жизненные ситуации описывают две фундаментальные структуры данных:

  • YouTube использует стек для кнопки “назад” в браузере
  • Instagram использует очередь для обработки загружаемых Stories
  • Telegram использует стек для отмены действий (Ctrl+Z)
  • Spotify использует очередь для плейлистов

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

В 1946 году Алан Тьюринг впервые описал концепцию стека при разработке автоматических вычислительных машин. Он заметил, что многие алгоритмы естественным образом используют принцип “последний пришёл - первый ушёл”.

Интересный факт: термин “stack overflow” (переполнение стека) дал название знаменитому сайту для программистов! 😄 А очереди были формализованы в теории массового обслуживания для оптимизации работы телефонных станций.

💡 Интуиция

Стек (Stack) = Стопка тарелок 🍽️

Когда моешь посуду, складываешь чистые тарелки друг на друга. Какую возьмёшь первой? Конечно, верхнюю - ту, что положил последней. Это и есть принцип LIFO (Last In, First Out).

Очередь (Queue) = Очередь в кассу 🛒

В магазине все встают в очередь и обслуживаются по принципу “кто первый пришёл, того первого обслуживают”. Это принцип FIFO (First In, First Out).

[МЕДИА: image_01] Описание: Визуальное сравнение стека тарелок и очереди в магазине Промпт: “educational illustration comparing stack of plates and queue at store checkout, LIFO vs FIFO concept, modern clean style, suitable for technical audience, arrows showing data flow”

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

Стек

Абстрактный тип данных с операциями:

  • push(x) - добавить элемент x на вершину
  • pop() - удалить и вернуть верхний элемент
  • top() - посмотреть верхний элемент (не удаляя)
  • isEmpty() - проверить, пуст ли стек
  • size() - количество элементов

Очередь

Абстрактный тип данных с операциями:

  • enqueue(x) - добавить элемент x в конец очереди
  • dequeue() - удалить и вернуть первый элемент
  • front() - посмотреть первый элемент
  • rear() - посмотреть последний элемент
  • isEmpty() - проверить, пуста ли очередь
  • size() - количество элементов

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

Пример 1: Проверка правильности скобок

Задача: проверить, правильно ли расставлены скобки в выражении “(()())”

def check_brackets(s):
    stack = []
    for char in s:
        if char == '(':
            stack.append(char)  # push
        elif char == ')':
            if not stack:  # isEmpty
                return False
            stack.pop()  # pop
    return len(stack) == 0  # isEmpty

Трассировка:

  1. ‘(’ → stack: [’(’]
  2. ‘(’ → stack: [’(’, ‘(’]
  3. ‘)’ → pop → stack: [’(’]
  4. ‘(’ → stack: [’(’, ‘(’]
  5. ‘)’ → pop → stack: [’(’]
  6. ‘)’ → pop → stack: []

Результат: True - скобки расставлены правильно!

[МЕДИА: image_02] Описание: Пошаговая трассировка проверки скобок со стеком Промпт: “step-by-step visualization of bracket checking algorithm using stack, animated sequence showing push and pop operations, programming education style”

Пример 2: Обработка заявок в техподдержку

Система обрабатывает заявки по принципу FIFO:

from collections import deque

support_queue = deque()

# Поступают заявки
support_queue.append("Заявка #1: Не работает WiFi")    # enqueue
support_queue.append("Заявка #2: Проблема с паролем")  # enqueue  
support_queue.append("Заявка #3: Медленный интернет")  # enqueue

# Обрабатываем заявки
while support_queue:
    current_ticket = support_queue.popleft()  # dequeue
    print(f"Обрабатываем: {current_ticket}")

Результат обработки:

  1. “Заявка #1: Не работает WiFi”
  2. “Заявка #2: Проблема с паролем”
  3. “Заявка #3: Медленный интернет”

🎮 Практика

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

Задание 1: Реализуй стек на основе списка Python. Добавь элементы [1, 2, 3], затем извлеки все элементы. В каком порядке они выйдут?

Задание 2: У тебя есть очередь принтера. Документы поступают в порядке: “Реферат.doc”, “Презентация.ppt”, “Фото.jpg”. В каком порядке они будут распечатаны?

Задание 3: Проверь правильность скобок в выражении “((())”. Объясни, почему оно неправильное.

Задание 4: В браузере ты посетил страницы A→B→C→D. Используя стек, покажи, какие страницы увидишь при нажатии кнопки “Назад” три раза.

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

Задание 5: Реализуй функцию, которая переворачивает строку с помощью стека.

Задание 6: В игре есть система отмены ходов (undo). Игрок сделал ходы: “влево”, “вверх”, “вправо”, “вниз”. Как организовать отмену с помощью стека?

Задание 7: Система обработки заказов в кафе использует две очереди: “срочные” и “обычные”. Как объединить их в одну систему обслуживания?

Задание 8: Создай алгоритм проверки правильности скобок трёх типов: (), [], {}

Челлендж 🔴

Задание 9: Реализуй стек с операцией getMin(), которая возвращает минимальный элемент за O(1).

Задание 10: Используя два стека, реализуй очередь (все операции очереди должны работать корректно).

Задание 11: Реализуй калькулятор для выражений в постфиксной записи (например: “3 4 + 2 ×” = 14) используя стек.

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

Ошибка: Путать push/pop со стандартными операциями списка ✅ Правильно: push = append, pop = pop (но только с конца!) 💡 Почему: В Python list.pop() работает как стек, но list.pop(0) - как очередь (медленно!)

Ошибка: Пытаться взять элемент из пустого стека/очереди ✅ Правильно: Всегда проверяй isEmpty() перед pop/dequeue 💡 Почему: Иначе получишь IndexError или пустое значение

Ошибка: Использовать list для очереди с операциями в начале ✅ Правильно: Используй collections.deque для эффективной очереди 💡 Почему: list.pop(0) работает за O(n), deque.popleft() - за O(1)

Ошибка: Думать, что стек и очередь - это только для программирования ✅ Правильно: Эти принципы везде: в браузере, играх, операционных системах 💡 Почему: Понимание принципов помогает видеть паттерны в окружающем мире

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

Стек (LIFO): последний пришёл - первый ушёл, как стопка тарелок ✅ Очередь (FIFO): первый пришёл - первый обслужился, как очередь в кассу
Применение: отмена операций, проверка скобок, обход графов, парсинг выражений

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

Стеки и очереди - основа для более сложных структур:

  • Деревья: обход в глубину использует стек, в ширину - очередь
  • Графы: алгоритмы поиска DFS (стек) и BFS (очередь)
  • Алгоритмы сортировки: быстрая сортировка использует стек вызовов
  • Динамическое программирование: мемоизация часто использует стек

В следующих уроках мы увидим, как эти простые концепции становятся основой для мощных алгоритмов!

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

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

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