Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
nestudent.ru_46905.doc
Скачиваний:
27
Добавлен:
12.09.2019
Размер:
2.07 Mб
Скачать

Глава 3. Стеки и очереди

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

Стеки

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

Стеки часто называют списками типа первый вошел — последний вышел (Last‑In‑First‑Out list). По историческим причинам, добавление элемента в стек называется проталкиванием (pushing) элемента в стек, а удаление элемента из стека — выталкиванием (popping) элемента из стека.

Первая реализация простого списка на основе массива, описанная в начале 2 главы, является стеком. Для отслеживания вершины списка используется счетчик. Затем этот счетчик используется для вставки или удаления элемента из вершины списка. Небольшое изменение — это новая процедура Pop, которая удаляет элемент из списка, одновременно возвращая его значение. При этом другие процедуры могут извлекать элемент и удалять его из списка за один шаг. Кроме этого изменения, следующий код совпадает с кодом, приведенным во 2 главе.

Dim Stack() As Variant

Dim StackSize As Variant

Sub Push(value As Variant)

StackSize = StackSize + 1

ReDim Preserve Stack(1 To StackSize)

Stack(StackSize) = value

End Sub

Sub Pop(value As Variant)

value = Stack(StackSize)

StackSize = StackSize - 1

ReDim Preserve Stack(1 To StackSize)

End Sub

=====49

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

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

Dim List() As Variant

Dim NumItems As Integer

' Инициализация массива.

:

' Протолкнуть элементы в стек.

For I = 1 To NumItems

Push List(I)

Next I

' Вытолкнуть элементы из стека обратно в массив.

For I = 1 To NumItems

Pop List(I)

Next I

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

Следующий код позволяет создать стек, если заранее известен его максимальный размер. Процедура Pop не изменяет размер массива. Когда программа заканчивает работу со стеком, она должна вызвать процедуру EmptyStack для освобождения занятой под стек памяти.

======50

Const WANT_FREE_PERCENT = .1 ' 10% свободного пространства.

Const MIN_FREE = 10 ' Минимальный размер.

Global Stack() As Integer ' Стековый массив.

Global StackSize As Integer ' Размер стекового массива.

Global Lastltem As Integer ' Индекс последнего элемента.

Sub PreallocateStack(entries As Integer)

StackSize = entries

ReDim Stack(1 To StackSize)

End Sub

Sub EmptyStack()

StackSize = 0

LastItem = 0

Erase Stack ' Освободить память, занятую массивом.

End Sub

Sub Push(value As Integer)

LastItem = LastItem + 1

If LastItem > StackSize Then ResizeStack

Stack(LastItem) = value

End Sub

Sub Pop(value As Integer)

value = Stack(LastItem)

LastItem = LastItem - 1

End Sub

Sub ResizeStack()

Dim want_free As Integer

want_free = WANT_FREE_PERCENT * LastItem

If want_free < MIN_FREE Then want_free = MIN_FREE

StackSize = LastItem + want_free

ReDim Preserve Stack(1 To StackSize)

End Sub

Этот вид реализации стеков достаточно эффективен в Visual Basic. Стек не расходует понапрасну память, и не слишком часто изменяет свой размер, особенно если сразу известно, насколько большим он должен быть.

=======51

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