Получить доступ

Чем стек отличается от очереди и где они применяются?

JuniorСтруктуры данных
Ещё спрашивают так:
  • Что такое LIFO и FIFO?
  • Как сделать очередь на двух стеках?
  • Где используется стек вызовов?
Коротко

Стек — последним пришёл, первым ушёл (LIFO); очередь — первым пришёл, первым ушёл (FIFO). Основные операции — O(1).

  • Стек: вызовы функций, отмена действий, проверка скобок, обход в глубину
  • Очередь: обработка задач по порядку, буферы, обход в ширину

А ещё Дек (deque) умеет оба конца и заменяет обе структуры

Так подсказку видит пользователь sotto на живом собеседовании — за пару секунд, пока вы думаете вслух.

Подробно

Стек поддерживает push (положить наверх), pop (снять верхний) и peek (посмотреть верхний). Где используется:

  • стек вызовов — при вызове функции её локальные переменные и адрес возврата кладутся на стек, при выходе снимаются. Слишком глубокая рекурсия переполняет его;
  • отмена действий (undo), история браузера «назад»;
  • проверка парности скобок, разбор выражений;
  • обход графа в глубину (DFS) без рекурсии.

Очередь поддерживает enqueue (в конец) и dequeue (из начала):

  • обработка задач в порядке поступления, очереди сообщений;
  • буферы ввода-вывода;
  • обход графа в ширину (BFS).

Реализация: стек — на динамическом массиве (операции с концом). Очередь на массиве с удалением из начала даёт O(n) на операцию — поэтому используют кольцевой буфер или связный список, а на практике — дек (deque в Python, ArrayDeque в Java), который добавляет и удаляет с обоих концов за O(1).

Классическая задача — очередь на двух стеках: кладём во входной стек, забираем из выходного; когда выходной пуст, перекладываем туда всё из входного. Каждый элемент перекладывается один раз, поэтому операции амортизированно O(1).

Пример

def balanced(s):
    pairs = {")": "(", "]": "[", "}": "{"}
    stack = []
    for ch in s:
        if ch in "([{":
            stack.append(ch)
        elif ch in pairs:
            if not stack or stack.pop() != pairs[ch]:
                return False
    return not stack

balanced("{[()]}")   # True
balanced("([)]")     # False

Что хотят услышать

  • LIFO и FIFO, основные операции и их сложность.
  • Примеры применения каждой структуры.
  • Почему очередь не делают на массиве с удалением из начала.
  • Очередь на двух стеках — плюс.

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

  • Реализовать очередь через удаление первого элемента массива — O(n).
  • Путать очередь и очередь с приоритетом.

Что спросят дальше

Связанные вопросы

Закрытая бета

Подсказки на собеседовании — в реальном времени

sotto слышит вопрос интервьюера и показывает короткий ответ и план, как в блоке «Коротко». Оставьте контакт — пришлём доступ и промокод.

  • Промокод на 2 часа — сверх пробных 30 минут
  • Программа для Windows — скачать сразу, войти — через Яндекс ID или VK ID
  • Прямая связь с разработчиком: что улучшить — сделаем