Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Лекции СД.doc
Скачиваний:
212
Добавлен:
19.03.2015
Размер:
1.81 Mб
Скачать
      1. 5.1.1. Стеки в вычислительных системах

Стек является удобной структурой данных для многих задач вычислительной техники. Наиболее типичной задачей является обеспечение вложенных вызовов процедур. Предположим, имеется процедура A, которая вызывает процедуру B, а та в свою очередь – процедуру C. Когда выполнение процедуры A дойдет до вызова B, процедура A приостанавливается и управление передается на входную точку процедуры B. Когда B доходит до вызова C, приостанавливается B и управление передается на процедуру C. Когда заканчивается выполнение процедуры C, управление должно быть возвращено в B, причем в точку, следующую за вызовом C. При завершении B управление должно возвращаться в A, в точку, следующую за вызовом B.

Правильную последовательность возвратов легко обеспечить, если при каждом вызове процедуры записывать адрес возврата в стек. В результате, когда процедура A вызывает процедуру B, в стек заносится адрес возврата в A; когда B вызывает C, в стек заносится адрес возврата в B. Когда C заканчивается, адрес возврата выбирается из вершины стека – а это адрес возврата в B. Когда заканчивается B, в вершине стека находится адрес возврата в A, и возврат из B произойдет в A.

Языки программирования блочного типа (PASCAL, C и др.) используют стек для размещения локальных переменных процедур и иных программных блоков. При каждой активизации процедуры память для ее локальных переменных выделяется в стеке, а при завершении процедуры память освобождается. Поскольку при вызовах процедур всегда строго соблюдается вложенность, то в вершине стека всегда находится память, содержащая локальные переменные активной в данный момент процедуры.

Такой прием делает возможной легкую реализацию рекурсивных процедур. Когда процедура вызывает саму себя, для всех ее локальных переменных выделяется память в стеке, и вложенный вызов работает с собственным представлением локальных переменных. Когда вложенный вызов завершается, занимаемая переменными область памяти в стеке освобождается и актуальным становится представление локальных переменных предыдущего уровня. За счет этого в языках PASCAL и C любые процедуры/функции могут вызывать сами себя. Рекурсия использует стек в скрытом виде, но все рекурсивные процедуры могут быть реализованы и без рекурсии с явным использованием стека.

    1. 5.2. Очереди fifo

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

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

Очевидно, со временем указатель на конец при очередном включении элемента достигнет верхней границы той области памяти, которая выделена для очереди. Если операции включения чередовались с операциями исключения элементов, то в начальной части отведенной под очередь памяти имеется свободное место. Чтобы места, занимаемые исключенными элементами, могли быть повторно использованы, очередь замыкается в кольцо: указатели (на начало и на конец), достигнув конца выделенной области памяти, переключаются на ее начало. Такая организация очереди в памяти называется кольцевой очередью.

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

Очистка очереди сводится к записи одного и того же (не обязательно начального) значения в оба указателя. Определение размера состоит в вычислении разности указателей с учетом кольцевой природы очереди.

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