Стек (компьютер)

Редактирование

Ctrl-w/u/k – вырезать слово/начало/конец строки

– вырезать слово (от текущего положения курсора до ближайшего ранее в строке пробела/табуляции). Вырезанное можно затем вставить комбинацией

– вырезать начало строки (от текущего положения курсора. Если курсор в конце строки, то вырежет целиком строку). Вырезанное можно затем вставить комбинацией .

– вырезать конец строки (от текущего положения курсора. Если курсор в начале строки, то вырежет целиком строку). Вырезанное можно затем вставить комбинацией .

Ctrl-y – вставить вырезанное

– вставить вырезанный фрагмент командной строки. (В bash используется свой буфер для хранения вырезанных фрагментов – называется «kill ring»).

Важно: Удобно использовать с (позволяет «прокручивать» варианты вставки из буфера)

Ctrl-x Ctrl-e – редактировать в $EDITOR

Нажав комбинацию , можно редактировать командную строку в любом внешнем редакторе (по умолчанию часто используется редактор vim; переназначить редактор можно, указав в переменной EDITOR). Часто редакторы имеют больше продвинутых возможностей в редактировании текста. Особенно удобно, если редактор умеет подкрашивать синтаксис команд и имеет различные встроенные инструменты для быстрого поиска и исправления ошибок.

Также эту возможность часто использую, когда набранную команду, разросшуюся до нескольких строк, хочу сохранить в виде отдельного скрипта – тогда переключаю редактирование команды в редактор и в нём сохраняю набранный текст в файл, как в примере ниже:

Что стоит учитывать при подборе стека

1. Требования и особенности проекта

При формировании тех. стека прежде всего необходимо учитывать размер и цель проекта, так как они значительно влияют на выбор технологий. Чем больше и масштабнее проект, тем больше и сложнее будет стек.

Так, например, для небольших проектов (MVP или одностраничные приложения) идеально могут подойти такие устоявшиеся стеки как Python-Django или Node.js-React.

Проекты средней величины, например, онлайн-магазины и приложения для среднего бизнеса, требуют немного более сложных технических стеков с несколькими уровнями языков программирования и фреймворками.

Крупные проекты, например, сложные торговые площадки или enterprise приложения, требуют масштабного стека для поддержания целостности и производительности приложений. Такие крупные технические стеки обычно используют несколько уровней языков программирования и фреймворков. Они созданы и используются для работы в условиях большого объема данных.

Важно помнить о том, что не стоит нагружать проект дополнительными технологиями. Их должно быть ровно столько, сколько необходимо для эффективного решения поставленной задачи

2. Опыт и ресурсы

Для того, чтобы подобрать тех стек, необходим хороший технический и архитектурный опыт и знания. Для грамотного подбора технологий необходимо ориентироваться в тонкостях и различиях каждой из них.

Соответственно, при формировании стека стоит отдавать предпочтение тем технологиям, с которыми вы работаете уверенно. Не стоит выбирать новую технологию ради новой технологии: часто новые фреймворки и языки программирования либо сырые, либо опытных разработчиков, работающих с этими технологиями, попросту нет. Выбор таких технологий может привести к тому, что разработчики проекта будут сидеть и разбирать новую технологию вместо эффективного движения вперед. Но, в тоже время, не стоит отдавать предпочтение чему-то устаревшему и неэффективному по причине того, что есть “знающие люди”. В подобных случаях могут возникнуть сложности с поддержкой и эффективностью проекта. Определяясь с технологиями, необходимо найти ту самую золотую середину.

Также, стоит учитывать наличие ресурсов для реализации проекта. Например, если в вашей команде нет специалиста, работающего с определенной технологией, добавлять ее в проект просто не имеет смысла. “Внушительный” стек не несет в себе никакой пользы, если нет разработчиков, способных успешно и быстро работать с выбранными технологиями.

3. Масштабируемость

Архитектура вашего приложения должна быть масштабируемой, так как масштабируемость — жизненно важна для дальнейшего развития. От масштабируемости зависит, справится ли ваше приложение с нагрузкой. Например, если количество пользователей увеличивается, ваш технологический стек должен позволять приложению справляться с этим ростом.

Существует два типа масштабируемости — горизонтальная и вертикальная. Первый означает возможность работы на разных устройствах и позволяет справляться с увеличивающимся количеством пользователей. Вертикальная масштабируемость означает возможность добавлять новые функции или элементы в приложение в будущем.

Для достижения хорошей масштабируемости лучше использовать мощные языки программирования, такие как JavaScript. Такие языки сами по себе гибкие, так как имеют в арсенале различные библиотеки и структуры.

4. Удобство обслуживания

Удобство обслуживания является одним из основных факторов при создании приложений. Обслуживание вашего приложения должно осуществляться без усилий даже при масштабировании.

В частности, есть два фактора, от которых зависит удобство обслуживания вашего приложения:

  • архитектура: должна поддерживать возможность повторного использования (reusability), быть мобильной и масштабируемой;
  • кодовая база (codebase): не должна быть слишком длинной и слишком краткой, так как для обработки длинного кода потребуется больше времени, а сжатый код может привести к ошибкам во время дебага.

5. Безопасность

Любой конечный пользователь хочет быть уверенным, что его личные данные в безопасности. Поэтому, при формировании стека, необходимо выбирать технологии, которые обеспечивают высокий уровень безопасности. Эта проблема существенна, особенно если говорить об онлайн-платежах.

6. Скорость разработки

Скорость разработки проекта — один из важнейших факторов. В случае, если проект должен быть разработан в сжатые сроки, оптимальным вариантом будет выбор готовых решений тех. стека, обеспечивающих простую интеграцию. Подобные комбинации технологий сокращают общее время разработки за счет сторонних интеграций.

Функция peek()

В библиотеку stack добавили новую функцию , с помощью которой вы можете обратиться к элементу стека (от вершины).

Ниже вы мы использовали функцию , чтобы вывести третий элемент:

setlocale(LC_ALL,»rus»);
stack <int> steck;

steck.push(5); // Добавляем
steck.push(1); // элементы
steck.push(9); // в
steck.push(10); // стек

cout << «Третий элемент стека: » << steck.peek(3); // выведет 1

1
2
3
4
5
6
7
8
9

setlocale(LC_ALL,»rus»);

stack<int>steck;

steck.push(5);// Добавляем

steck.push(1);// элементы

steck.push(9);// в

steck.push(10);// стек

cout<<«Третий элемент стека: «<<steck.peek(3);// выведет 1

Функцию использует маленький круг программистов и надо сразу сказать эта функция не стала столь востребованной, как от нее ожидали создатели.

Стек и особенности его работы

Перейдя к компьютерной терминологии, скажем, что стек — это область оперативной памяти, создаваемая для каждого потока. И последний добавленный в стек кусочек памяти и будет первым в очереди, то есть первым на вывод из стека. И каждый раз, когда функцией объявляется переменная, она, прежде всего, добавляется в стек. А когда данная переменная пропадает из нашей области видимости (к примеру, функция заканчивается), эта самая переменная автоматически удаляется из стека. При этом если стековая переменная освобождается, то и область памяти, в свою очередь, становится доступной и свободной для других стековых переменных.

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

Тем не менее у данной довольно строгой формы управления имеются и свои недостатки. Например, размер стека — это величина фиксированная, в результате чего при превышении лимита памяти, выделенной на стеке, произойдёт переполнение стека. Как правило, размер задаётся во время создания потока, плюс у каждой переменной имеется максимальный размер, который зависит от типа данных. Всё это позволяет ограничивать размеры некоторых переменных (допустим, целочисленных).

Кроме того, это вынуждает объявлять размер более сложных типов данных (к примеру, массивов) заранее, так как стек не позволит потом изменить его. Вдобавок ко всему, переменные, которые расположены на стеке, являются всегда локальными.

Стек

Стек – наверное, самая простая структура данных, которую мы будем изучать и которой будем постоянно
пользоваться. Стек – это структура данных, в которой элементы поддерживают принцип LIFO (“Last in – first out”): последним зашёл –
первым вышел. Или первым зашёл – последним вышел.

Стек позволяет хранить элементы и поддерживает, обычно, две базовые операции:

  • PUSH – кладёт элемент на вершину стека
  • POP – снимает элемент с вершины стека, перемещая вершину к следующему элементу

Также часто встречается операция PEEK, которая получает элемент на вершине стека, но не снимает его оттуда.

Стек является одной из базовых структур данных и используется не только в программировании, но и в схемотехнике, и просто в
производстве, для реализации технологических процессов и т.д.; стек используется в качестве вспомогательной структуры данных во
многих алгоритмах и в других более сложных структурах.

Пусть, например, у нас есть стек чисел. Выполним несколько команд.
Изначально стек пуст. Вершина стека – указатель на первый элемент, никуда не указывает. В случае си она может быть равна NULL.

Теперь стек состоит из одного элемента, числа 3. Вершина стека указывает на число 3.

Стек состоит из двух элементов, 5 и 3, при этом вершина стека указывает на 5.

Стек состоит из трёх элементов, вершина стека указывает на 7.

Вернёт значение 7, в стеке останется 5 и 3. Вершина будет указывать на следующий элемент – 5.

Вернёт 5, в стеке останется всего один элемент, 3, на который будет указывать вершина стека.

Вернёт 3, стек станет пуст.

Последовательное выполнение операций push 3, push 5, push 7, pop, pop, pop

Часто сравнивают стек со стопкой тарелок. Чтобы достать следующую тарелку, необходимо снять предыдущие. Вершина стека –
это вершина стопки тарелок.

Когда мы будем работать со стеком, возможны две основные и часто встречающиеся ошибки:

  • 1. Stack Underflow: Попытка снять элемент с пустого стека
  • 2. Stack Overflow: Попытка положить новый элемент на стек, который не может больше расти (например, не хватает оперативной памяти)

Пример работы со стеком

Рассмотрим пример работы со стеком на небольшой задаче. Допустим, нам необходимо сохранить значения регистров eax, ebx и edx в стеке, потом произвести с ними необходимые действия и вернуть исходные значения этих регистров. На ассемблере это будет выглядеть так:

push eax // Помещаем в стек значение регистра eax. // При этом указатель стека (esp) уменьшится на размер регистра eax, // т.е. на 4 байта (значение esp уменьшится на 4) push ebx // Аналогично, только в стек поместится значение регистра ebx push edx // То же самое, только в стек помещается значение регистра edx ……. // Тут производим какие-то действия с регистрами eax, ebx, edx так, // что значения этих регистров изменяются pop edx // Берем значение из стека (по адресу esp) и помещаем это значение в регистр edx.

Стек вызовов в действии

Давайте подробнее рассмотрим, как работает стек вызовов. Вот последовательность шагов, которые выполняются при вызове функции:

  1. Программа обнаруживает вызов функции.
  2. Кадр стека создается и помещается в стек. Кадр стека состоит из:
    • Адрес инструкции, следующей после вызова функции (называемый адресом возврата). Таким образом, CPU запоминает, куда вернуться после выхода из вызываемой функции.
    • Все аргументы функции.
    • Память для любых локальных переменных.
    • Сохраненные копии любых регистров, измененных функцией, которые необходимо восстановить после возврата из функции.
  3. CPU переходит к начальной точке функции.
  4. Инструкции внутри функции начинают выполняться.

Когда функция завершается, происходят следующие шаги:

  1. Регистры восстанавливаются из стека вызовов
  2. Кадр стека извлекается из стека. Это освобождает память для всех локальных переменных и аргументов.
  3. Обрабатывается возвращаемое значение.
  4. CPU возобновляет выполнение по адресу возврата.

Возвращаемые значения могут обрабатываться разными способами в зависимости от архитектуры компьютера. Некоторые архитектуры включают возвращаемое значение как часть кадра стека. Другие используют регистры CPU.

Обычно неважно знать все подробности о том, как работает стек вызовов. Однако понимание того, что функции помещаются в стек при их вызове и удаляются при возврате, дает вам основы, необходимые для понимания рекурсии, а также некоторые другие концепции, полезные при отладке

Техническое примечание: на некоторых архитектурах стек вызовов при увеличении изменяет адрес памяти в направлении от нуля. На других он при увеличении изменяет адрес в направлении нуля. Как следствие, новые добавленные кадры стека могут иметь более высокий или более низкий адрес памяти, чем предыдущие.

Другие лучшие технологические стеки

В то время как MEAN и LAMP являются ведущими технологическими стеками на рынке прямо сейчас, существует множество других стеков, доступных для нишевых ситуаций и решений. Некоторые из них представляют собой всего лишь вариации двух больших стеков, а другие представляют собой новаторских игроков на рынке.

Давайте кратко рассмотрим эти почетные упоминания.

MERN

Стек MERN — это вариант MEAN, который заменяет Angular.js на React.

React использует виртуальную модель DOM для упрощения изменений пользовательского интерфейса и оптимизирован для высокореактивных одностраничных приложений. React также использует JSX для гибкого управления компонентами. Самым большим недостатком React является то, что в его базовом состоянии отсутствуют функции в виде библиотеки, а не полнофункционального фреймворка.

Замена Angular на React по сути жертвует функциями ради простоты использования и гибкости.

Преимущества:

  • Повышенная простота использования по сравнению с MEAN без ущерба для возможностей разработки полного стека
  • Оптимизирован для СПА
  • Разработчиков React больше, чем разработчиков Angular.js.

Недостатки:

  • Жертвовать некоторой функциональностью без полноценного фреймворка
  • Модули, необходимые для заполнения некоторых недостающих функций

Пример использования:

Вы хотите в кратчайшие сроки создать простое или промежуточное одностраничное приложение, или ваша команда уже знакома с React.

MEVN

Подобно MERN, MEVN заменяет Angular.js на Vue.js.

Vue — это фреймворк, который предлагает минималистский подход, ориентированный на производительность. Он более легкий, чем Angular.js или React, и поставляется со всеми основными функциями «из коробки». Vue также можно дополнить сторонними сервисами, чтобы заполнить любую нишу, соответствующую вашим потребностям. Самым большим недостатком Vue является то, что он не используется широко и может не иметь поддержки сообщества или интеграции, которой пользуются React или Angular.

Vue — это, по сути, базовый фреймворк, который жертвует причудливыми функциями и некоторым контролем, чтобы его можно было быстро и легко настроить.

Преимущества:

  • Быстрее, чем у React и Angular
  • Готовы выйти прямо из коробки
  • Рентабельность благодаря простоте использования

Недостатки:

  • Не хватает ресурсов как наименее популярного из трех фреймворков.
  • Довольно новый, то есть вам придется часто обновлять

Пример использования:

Вы ищете максимальную производительность и не планируете добавлять какие-либо необычные функции приложения.

Ruby on Rails (RoR)

Ruby on Rails — это удобный для разработчиков технологический стек, построенный на самоуверенном языке программирования Ruby. Он уникален тем, что содержит все инструменты стандартного технического стека в одном пакете. Он также изначально интегрирован с HTML, CSS и JavaScript.

RoR призван максимально упростить вашим веб-разработчикам создание нового приложения благодаря обязательным передовым методикам и встроенным структурам по умолчанию. Он также предлагает улучшенную производительность, поскольку все инструменты полностью интегрированы, чтобы упростить управление пользовательским интерфейсом.

Преимущества:

  • Быстрое развертывание новых приложений с использованием структур по умолчанию
  • Надежная система обнаружения ошибок
  • Легкий

Недостатки:

  • Не очень настраиваемый
  • Довольно редко

Пример использования:

Вы хотите создать надежное веб-приложение как можно быстрее и не нужно, чтобы оно было слишком сложным.

Бессерверный

Развитие облачных вычислений привело к тому, что многие компании перешли от управления собственной инфраструктурой приложений к созданию безсерверных облачных приложений. Эти бессерверные приложения позволяют облачному провайдеру, например AWS или Azure, обрабатывать все услуги и инструменты по цене, соответствующей масштабу вашей компании.

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

Преимущества

  • Экономично для малого бизнеса и стартапов
  • Нет необходимости управлять собственными технологиями или поддерживать их

Недостатки

  • Меньший контроль над тем, какие технологии находятся в стеке
  • Затраты на масштабирование сделают это неэффективным сверх определенного размера.

Пример использования:

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

История команд

«Работа с историей команд» – классическая тема обычно из любого начального курса по Linux (по крайней мере, среди тех курсов, которые читаются у нас в «Сетевой Академии ЛАНИТ»). И многие, кто имеет хотя бы небольшой опыт работы с командной строкой, историей команд пользуются – как минимум знают, что она есть, и используют стрелки «вверх» (отобразить предыдущую команду) и «вниз» (отобразить следующую после отображаемой команду в истории команд), чтобы выбрать, какую из ранее введенных команд либо снова выполнить, либо подредактировать и запустить отредактированную. Но помимо стрелок еще есть ряд полезных комбинаций клавиш, которые позволяют работать с историей команд, – быстрее находить нужные команды.

Ctrl-r – Поиск по истории

Комбинация позволяет искать в истории команд команды, содержащие указанный далее текст.

^^^ В этом примере мне понадобилось из истории вытащить команду, содержащую текст «su»: нажав и набрав искомый текст «su», я увидел самую недавнюю команду, содержащую «su»; при повторном нажатии отображается предыдущая команда, содержащая «su» и т.д. При необходимости изменить команду жму стрелку «вправо» и правлю текст, а чтобы запустить команду — нажимаю .

PgUp/PgDown – Поиск по истории

– отображает предыдущую команду начинающуюся с уже введенного текста, – следующую.

^^^ В этом примере перемещаюсь между командами, начинающимися с «cat». (Часто также ищу команды, начинающиеся с «sudo». Или если мне нужно снова отредактировать какой-то файл, который недавно редактировал: набираю «vi», жму несколько раз , а затем .)

Alt-_/Alt-./Alt— – вставка аргументов

Комбинация (выполняется нажатием , , ) – вставляет последний аргумент из предыдущих команд. (Аналогично работает комбинация или, что то же самое, )

^^^ В данном примере видно, как повторные нажатия вставляют аргументы от пред-пред-…-идущих команд.

Комбинация – позволяет указать (порядковый номер с конца), какой аргумент вставить клавишей из предыдущей команды.

^^^ В данном примере вставляю в командную строку различные аргументы из предыдущей команды.

Alt-# – текущую команду преобразовать в комментарий

Бывает, во время набора очень длинной команды понимаю, что мне нужно что-нибудь посмотреть или дополнительно сделать (например, глянуть, какие файлы есть в определенной директории, прочитать мануал по команде, установить нужный пакет…). Что делать с уже набранным текстом? Хотелось бы посмотреть нужную информацию и продолжить набирать команду, а не начинать печатать её сначала. (выполняется нажатием , , . Также можно использовать ) – преобразует текущую набранную команду в комментарий в истории – добавляет символ «#» в начало строки и добавляет полученную строку в историю команд.

Ctrl-o – повтор команд из истории

Комбинация позволяет повторять серию команд из истории. То есть нужно из истории команд стрелками выбрать первую команду из серии и нажать – это выполнит текущую команду и выведет из истории следующую. Дальше можно продолжать нажимать с тем же эффектом.

^^^ В примере я написал три команды: одна увеличивает на 1 переменную, которой соответствует год; вторая выводит переменную-год; третья показывает, сколько дней в феврале в указанном году. Дальше, нажимая , повторяю эту серию из трех команд много раз (один кадр соответствует трем нажатиям).

Переменные в стеке и куче

Память управляется автоматически в стеке, а переменные распределяются и автоматически освобождаются, что означает, что стек зарезервирован только для временных переменных. Локальные переменные становятся активными, когда функция выполняется, и когда она завершается, переменные выходят из области видимости, что означает, что область действия является локальной для функции и существует до тех пор, пока эта функция выполняется. В отличие от стека, память выделяется, поскольку программа работает в куче, что делает ее немного медленнее для доступа к хранящимся здесь переменным. Поскольку в резервировании блоков нет конкретного порядка, блоки памяти могут быть выделены и освобождены в любое время.

Использовать

Обработка звонков на сайт

Обычно манипуляции со стеком вызовов, необходимые на месте вызова подпрограммы, минимальны (что хорошо, поскольку может быть много узлов вызова для каждой вызываемой подпрограммы). Значения фактических аргументов оцениваются на сайте вызова, поскольку они специфичны для конкретного вызова, и либо помещаются в стек, либо помещаются в регистры, как определено используемым соглашением о вызовах . Фактическая инструкция вызова, такая как «переход и ссылка», затем обычно выполняется для передачи управления коду целевой подпрограммы.

Обработка записи подпрограммы

В вызываемой подпрограмме первый выполненный код обычно называется прологом подпрограммы , так как он выполняет необходимые служебные действия до того, как будет запущен код для операторов подпрограммы.

Для архитектур с набором команд, в которых инструкция, используемая для вызова подпрограммы, помещает адрес возврата в регистр, а не помещает его в стек, пролог обычно сохраняет адрес возврата, помещая значение в стек вызовов, хотя, если вызываемый подпрограмма не вызывает никаких других подпрограмм, она может оставить значение в регистре. Точно так же могут быть переданы значения текущего указателя стека и / или указателя кадра.

Если используются указатели кадра, пролог обычно устанавливает новое значение регистра указателя кадра из указателя стека. Затем можно выделить пространство в стеке для локальных переменных путем постепенного изменения указателя стека.

Язык программирования Forth допускает явную намотку стека вызовов (называемого там «стеком возврата»).

Обработка возврата

Когда подпрограмма готова к возврату, она выполняет эпилог, отменяющий шаги пролога. Обычно это восстанавливает сохраненные значения регистров (например, значение указателя фрейма) из фрейма стека, выталкивает весь фрейм стека из стека, изменяя значение указателя стека, и, наконец, выполняет переход к инструкции по адресу возврата. Согласно многим соглашениям о вызовах элементы, извлекаемые из стека эпилогом, включают в себя исходные значения аргументов, и в этом случае обычно нет дополнительных манипуляций со стеком, которые должны выполняться вызывающей стороной. Однако с некоторыми соглашениями о вызовах ответственность за удаление аргументов из стека после возврата лежит на вызывающей стороне.

Размотка

Возврат из вызванной функции вытолкнет верхний фрейм из стека, возможно, оставив возвращаемое значение. Более общий акт выталкивания одного или нескольких кадров из стека для возобновления выполнения в другом месте программы называется раскручиванием стека и должен выполняться, когда используются нелокальные управляющие структуры, такие как те, которые используются для . В этом случае кадр стека функции содержит одну или несколько записей, определяющих обработчики исключений. Когда генерируется исключение, стек разворачивается до тех пор, пока не будет найден обработчик, готовый обработать (перехватить) тип выброшенного исключения.

В некоторых языках есть другие управляющие структуры, требующие общей раскрутки. Паскаль позволяет глобальному оператору goto передавать управление из вложенной функции в ранее вызванную внешнюю функцию. Эта операция требует, чтобы стек был размотан, удалив столько кадров стека, сколько необходимо для восстановления правильного контекста, чтобы передать управление целевому оператору внутри включающей внешней функции. Аналогично, С имеет и функцию , которые действуют как нелокальный GOTOS. Common Lisp позволяет контролировать то, что происходит при разворачивании стека, с помощью специального оператора.

При применении продолжения стек (логически) разматывается, а затем перематывается вместе со стеком продолжения. Это не единственный способ реализовать продолжения; например, используя несколько явных стеков, приложение продолжения может просто активировать свой стек и намотать значение, которое нужно передать. Язык программирования Scheme позволяет выполнять произвольные переходы в определенных точках при «раскручивании» или «перемотке» стека управления при вызове продолжения.

Стек как структура данных

Структура данных в программировании — это механизм организации данных для их эффективного использования. Вы уже видели несколько типов структур данных, например, массивы или структуры. Существует множество других структур данных, которые используются в программировании. Некоторые из них реализованы в Стандартной библиотеке C++, и стек как раз является одним из таковых.

Например, рассмотрим стопку (аналогия стеку) тарелок на столе. Поскольку каждая тарелка тяжелая, а они еще и сложены друг на друге, то вы можете сделать лишь что-то одно из следующего:

   Посмотреть на поверхность первой тарелки (которая находится на самом верху).

   Взять верхнюю тарелку из стопки (обнажая таким образом следующую тарелку, которая находится под верхней, если она вообще существует).

   Положить новую тарелку поверх стопки (спрятав под ней самую верхнюю тарелку, если она вообще была).

В компьютерном программировании стек представляет собой контейнер (как структуру данных), который содержит несколько переменных (подобно массиву). Однако, в то время как массив позволяет получить доступ и изменять элементы в любом порядке (так называемый «произвольный доступ»), стек более ограничен.

В стеке вы можете:

   Посмотреть на верхний элемент стека (используя функцию или ).

   Вытянуть верхний элемент стека (используя функцию ).

   Добавить новый элемент поверх стека (используя функцию ).

Стек — это структура данных типа LIFO (англ. «Last In, First Out» = «Последним пришел, первым ушел»). Последний элемент, который находится на вершине стека, первым и уйдет из него. Если положить новую тарелку поверх других тарелок, то именно эту тарелку вы первой и возьмете. По мере того, как элементы помещаются в стек — стек растет, по мере того, как элементы удаляются из стека — стек уменьшается.

Например, рассмотрим короткую последовательность, показывающую, как работает добавление и удаление в стеке:

Стопка тарелок довольно-таки хорошая аналогия работы стека, но есть лучшая аналогия. Например, рассмотрим несколько почтовых ящиков, которые расположены друг на друге. Каждый почтовый ящик может содержать только один элемент, и все почтовые ящики изначально пустые. Кроме того, каждый почтовый ящик прибивается гвоздем к почтовому ящику снизу, поэтому количество почтовых ящиков не может быть изменено. Если мы не можем изменить количество почтовых ящиков, то как мы получим поведение, подобное стеку?

Во-первых, мы используем наклейку для обозначения того, где находится самый нижний пустой почтовый ящик. Вначале это будет первый почтовый ящик, который находится на полу. Когда мы добавим элемент в наш стек почтовых ящиков, то мы поместим этот элемент в почтовый ящик, на котором будет наклейка (т.е. в самый первый пустой почтовый ящик на полу), а затем переместим наклейку на один почтовый ящик выше. Когда мы вытаскиваем элемент из стека, то мы перемещаем наклейку на один почтовый ящик ниже и удаляем элемент из почтового ящика. Всё, что находится ниже наклейки — находится в стеке. Всё, что находится в ящике с наклейкой и выше — находится вне стека.