Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
SAOD_L_1.doc
Скачиваний:
8
Добавлен:
12.11.2018
Размер:
537.09 Кб
Скачать

  1. Стеки. Очереди.

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

Основные сведения

Стеки и очереди – это динамические структуры данных с ограниченным видом операций включения новых и исключения имеющихся элементов.

Стек представляет собой последовательность элементов с одной точкой доступа, называемой вершиной стека. Все элементы последовательности, кроме элемента, расположенного в вершине стека, не доступны. Новый элемент добавляется только в вершину стека, сдвигая остальные элементы последовательности. Исключить можно только элемент из вершины стека, остальные элементы последовательности при этом сдвигаются в сторону вершины стека. Таким образом, стек работает по принцип «последним пришел – первым ушел» и часто называется структурой LIFO (Last In – First Out).

В алгоритмах операцию добавления элемента в стек будем записывать в виде S  x (элемент x поместить в вершину стека S), а операцию исключения из стека – в виде x  S (исключить элемент из вершины стека S и присвоить его значение переменной x). В литературе эти операции традиционно называют PUSH (добавление) и POP (исключение).

Одним из эффективных способов реализации стека является использование последовательного распределения (массива). Наряду с массивом достаточно иметь переменную t (указатель вершины стека), являющуюся индексом последнего добавленного в стек элемента. Стек состоит из элементов S(1), S(2), …, S(t), где S(1) – нижний элемент (дно) стека, а S(t) – верхний элемент (вершина) стека. Емкость стека определяется размером массива. Пусть для реализации стека выделен массив из m компонентов, тогда всегда должно выполняться условие t  m, в противном случае при добавлении элемента происходит переполнение, что означает ошибку. Пустой стек соответствует случаю t = 0 и, как правило, означает окончание алгоритма.

Операции включения и исключения имеют следующий вид:

Для некоторых алгоритмов проверку пустоты стека целесообразно выделить в отдельную операцию со стеком (в алгоритмах будем записывать в виде S = ). Все операции со стеком выполняются за время O(1).

На рис. 1 показана реализация стека на базе массива: а – стек содержит 4 элемента, верхний элемент – число 9; б – тот же стек после выполнения операций S  3 и S  8; в – стек после исключения элемента из вершины стека (число 8). Хотя число 8 по прежнему присутствует в массиве, в стеке его уже нет, т. к. вершина стека – число 3.

Рис. 1

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

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

В алгоритмах операцию включения элемента в очередь будем записывать в виде Q  x (элемент x помещается в конец очереди Q), а операцию исключения из очереди – в виде x  Q (исключить элемент из начала очереди Q и присвоить его значение переменной x).

Последовательная реализация очереди требует специальных приемов. Это связано с тем, что очередь растет на одном конце и убывает на другом, т. е. двигается в сторону правой границы массива и может ее перейти, хотя в левой части массива может быть достаточно места для размещения элементов очереди. Чтобы этого избежать, необходимо массив свернуть в кольцо. Для этого удобно использовать операцию mod (вычисление остатка от целочисленного деления). В этом случае для очереди Q выделяется массив из m компонентов Q(0), Q(1), Q(2), …, Q(– 1) и, в соответствии с операцией mod, считается, что Q(0) следует за Q(– 1). Если использовать переменную f в качестве указателя ячейки, расположенной непосредственно перед началом очереди, а переменную r в качестве указателя ее конца, то очередь будет состоять из элементов Q(+ 1), Q(+ 2), …, Q(r). Пустая очередь будет соответствовать случаю r = f. Тогда операции включения и исключения будут иметь следующий вид:

Как и в случае стеков, переполнение означает ошибку, а пустота очереди – окончание работы алгоритма. Следует обратить внимание на то, что переполнение появляется, когда к очереди из m – 1 элементов добавляется m-й элемент, поэтому одна из отведенных m ячеек остается пустой (емкость очереди равна m – 1).

Для ряда алгоритмов проверку пустоты очереди целесообразно выделить в отдельную операцию с очередью (в алгоритмах будем записывать в виде Q = ). Все операции с очередью выполняются за время O(1).

На рис. 2 показана реализация очереди на базе массива: а – очередь содержит 4 элемента, начало очереди – число 2, конец очереди – число 9; б – очередь после выполнения операций Q  3 и Q  8; в – очередь после исключения элемента из начала очереди (числа 2), новое начало очереди – число 5.

Р ис. 2

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

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

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]