Стеки
Чтобы проверить, что скобки в {[()()]} правильно образуют пары, нужен один стек и 8 добавлений и извлечений, по одному на каждую скобку.
Последним пришёл, первым ушёл
Представь стопку тарелок. Чистую тарелку кладёшь наверх, а когда нужна тарелка, берёшь сверху. Тарелка, положенная последней, уходит первой. Стек является структурой данных ровно с этим правилом, оно называется «последним пришёл, первым ушёл» (LIFO). У него две главные операции: push кладёт значение наверх, а pop снимает верхнее значение и возвращает его. Многие стеки предлагают и peek, которая смотрит на верх, ничего не снимая.
В конспектах MIT 6.006 стек является частным случаем интерфейса последовательности: insert last(x) и delete last(). Это уже подсказывает, как его построить. Положи значения в динамический массив и считай конец массива верхом. В прошлом уроке конец был дешёвой стороной, поэтому push и pop стоят по 1 шагу (амортизированно, из-за редких копирований). Размер стека ничего не меняет. Снять значение со стека из 3 значений или из 3 миллионов значит сделать один и тот же шаг.
const stack = [];
stack.push(4);
stack.push(8);
stack.push(5);
console.log(stack.pop()); // 5, добавлено последним
console.log(stack[stack.length - 1]); // peek: 8
console.log(stack.length); // 2Перетащи, чтобы повернуть. Колёсико или щипок для масштаба.
Проверка скобок
Классическое применение стека: проверка, сбалансированы ли скобки, это делает каждый редактор кода и компилятор. Читай текст слева направо. Каждая открывающая скобка, (, [ или {, кладётся в стек. Каждая закрывающая скобка должна совпадать с открывающей на верху стека: если совпадает, сними эту открывающую; если стек пуст или наверху скобка другого вида, строка не сбалансирована. В конце стек должен быть пуст, иначе какая-то открывающая скобка так и не закрылась.
Попробуй строки в лаборатории. {[()()]} требует 4 добавления и 4 извлечения, 8 шагов, и заканчивается пустым стеком. ([)] ломается на третьем символе: ) приходит, когда наверху [. (() дочитывается до конца, и одна ( остаётся лишней. Почему для этой работы подходит стек? Скобки вкладываются друг в друга, и последняя открытая должна закрыться первой. Это и есть «последним пришёл, первым ушёл».
Где ещё встречаются стеки
- Стек вызовов. Когда функция a вызывает b, а b вызывает c, компьютер кладёт запись для каждого вызова. Когда c возвращает результат, её запись снимается, и b продолжает с того места, где остановилась. Бесконечная рекурсия переполняет этот стек, отсюда ошибка «переполнение стека» (stack overflow).
- Отмена. Редактор кладёт в стек каждое изменение. Отмена снимает последнее изменение и откатывает его.
- Кнопка «Назад». Браузер кладёт в стек каждую страницу, с которой ты уходишь; «Назад» снимает последнюю.
- Поиск в глубину. В курсе об алгоритмах стек помогал зайти в лабиринте как можно глубже, прежде чем возвращаться.
- В каком порядке стек возвращает значения?
- Первым пришёл, первым ушёл
- Последним пришёл, первым ушёл
- Сначала наименьшее
- В случайном порядке
- Стек пуст. Push 4, push 8, push 5, pop, push 2. Что наверху?
- 4
- 8
- 5
- 2
- Сколько значений в стеке после этих операций?
- Push A, затем B, затем C, затем pop, пока стек не опустеет. Расставь снятые значения по порядку.
- Сколько всего добавлений и извлечений нужно, чтобы проверить {[()()]} способом со скобками?
- Если проверять ([)] слева, где проверка ломается?
- На первой (
- На [
- На )
- На последней ]
- Что не так с (() ?
- Закрывающая скобка приходит при пустом стеке
- В конце в стеке остаётся одна (
- Не хватает квадратных скобок
- Всё в порядке; строка сбалансирована
- Сколько шагов занимает pop из стека (хранящегося в динамическом массиве), в котором 1000 значений?
- Функция main вызывает draw, а draw вызывает line. Чья запись лежит на верху стека вызовов, пока выполняется line?
- main
- draw
- line
- ничья
- В каком году Бауэр и Замельзон подали заявку на патент на метод стека?
- 1946
- 1957
- 1962
- 1972
- Стек работает по правилу «последним пришёл, первым ушёл»: push кладёт наверх, pop снимает сверху.
- Если стек построен на конце динамического массива, push и pop стоят по 1 шагу.
- Проверка скобок кладёт открывающие в стек и снимает по одной на каждой закрывающей; {[()()]} требует 8 шагов.
- Стек вызовов, отмена и кнопка «Назад» являются стеками.
Источники курса (11)
- MIT OpenCourseWare 6.006 Introduction to Algorithms, Spring 2020 (Demaine, Ku, Solomon)
- lecture notes 2 Data Structures (interface vs data structure, Sequence and Set interfaces, stack = insert_last/delete_last, queue = insert_last/delete_first, array, linked list, dynamic array, amortized Θ(1) append)
- 4 Hashing (chaining, pigeonhole collisions, chain length n/m)
- 6 Binary Trees Part 1 (height, traversal order, O(h) operations) and 7 Binary Trees Part 2: AVL (Adelson-Velsky and Landis, 1962) at ocw.mit.edu/courses/6-006-introduction-to-algorithms-spring-2020/pages/lecture-notes
- MDN Web Docs, Array.prototype.shift (shifts all values left by 1)
- Array.prototype.unshift, Map (insertion order, Map vs Object, spec requires sublinear average access) and Set (developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects)
- ECMAScript 2025 Language Specification (tc39.es/ecma262)
- 24.1 Map Objects and 24.2 Set Objects ("must be implemented using either hash tables or other mechanisms that, on average, provide access times that are sublinear on the number of elements")
- Array.prototype.shift steps (Repeat, while k < len: move element k to k - 1)
- D. E. Knuth, The Art of Computer Programming vol. 3 (2nd ed. 1998) section 6.4 History (H. P. Luhn, IBM internal memorandum January 1953, hashing with chaining; digit pairs added mod 10, 31415926 -> 4548) via gwern.net copy, and IEEE Spectrum, "Hans Peter Luhn and the Birth of the Hashing Algorithm" (2018)
- "A brief history of the stack", SIGCIS (sigcis.org/files/A brief history.pdf: Bauer and Samelson applied for the patent in 1957, US 3,047,228 granted July 31, 1962; IPL list processing by Newell, Simon and Shaw at RAND 1956) and Wikipedia, Information Processing Language (Newell, Shaw, Simon, RAND and Carnegie Institute of Technology, about 1956).
Проверено: 2026-10-18