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

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

Ранее мы рассматривали алгоритмы сортировки, используя за основу массив. Почему? Массивы отлично подходят для описания, если можно так сказать, реляционной структуры. Используя их мы можем получить доступ к любому элементу по индексу, записать элемент в массив, изменить, сортировать, удалять элементы. Поэтому такие массивоподобные структуры данных (списки, деревья, графы, связные списки и т.д.) отлично подходят для задач, где такого рода операции выполняются часто. Это может быть база данных сотрудников или склада помидоров. Задачи, в которых нам необходим функционал массивов. Структура данных стек (хотя то что будет написано далее справедливо и для очередей, и приоритетных очередей) используется разработчиками чаще как внутренний инструмент, облегчающий написания самой программы и ее алгоритмов. Другими словами, массив – работает со внешними данными, стек – для особенных манипуляций с этими данными. В общем стек – другой уровень абстракции. За счет чего для реализации некоторых алгоритмов он предпочтительнее массива? Благодаря ограничениям, которые накладываются на стек для работы с данными, мы получаем отличный инструмент для решения задач определенного вида.

Теперь наконец дадим определение. Стек – структура данных, основанная на массиве, реализующая парадигму работы с данными по принципу FIFO (First In First Out – первый вошел, первый вышел). Эта парадигма накладывает на стек ограничения работы с данными: доступ только к элементу лежащему на вершине стека, вставка и извлечение элемента только с вершины. Используя стек мы имеем доступ только к ОДНОМУ элементу. Для того чтобы извлечь из стека элемент со дна, необходимо извлечь все элементы.

Реализуем стек целых чисел с помощью средств языка Java.

Вывод:

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

Задача “Поиск парных скобок”

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

с(в) – правильно.

с(р{ – неправильно

{([s])} – правильно.

Для решения задачи воспользуемся стеком, состоящим из элементов типа char. Каждый раз проходя по введенной строке мы будем складывать в стек открывающуюся скобку, далее встречая соответствующую ей закрывающуюся скобку – извлекать. При корректно введенной строке стек будет пустым, потому что на каждую открытую скобку будет своя закрытая.

Ввод

Вывод

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

Эффективность стеков

Реализованный нами стек позволяет извлекать и вставлять элементы за время O(1), т.е. независимо от размеров стека.

Оставить комментарий:

Ваш email не будет опубликован.