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

2. Линейные структуры данных

К линейным структурам данных относятся различные виды линейных списков.

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

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

Далее будет рассмотрено два основных подхода к обработке линейных списков — итеративная обработка списка с выделенным текущим элементом и рекурсивная обработка списка. При изложении первого подхода отдельно рассмотрим однонаправленные и двунаправленные списки (Л1-списки и Л2-списки [12]), а также особенности кольцевых списков.

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

2.1. Атд "Стек", "Очередь", "Дек"

2.1.1. Функциональная спецификация стека

Стек (stack) это специальный тип списка, в котором все вставки и удаления элементов выполняются только на одном конце, называемом вершиной (top). Такой метод доступа обозначается аббревиатурой LIFO (last-in-first-out — последним пришел — первым вышел).

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

  1. Создание пустого стека — операция Create;

  2. Проверка стека на наличие в нем хотя бы одного элемента — предикат (логическая функция) IsNull.

  3. Получение элемента из вершины непустого стека — операция GetTop;

  4. Удаление элемента с вершины непустого стека (элемент выталкивается из стека)  — операция Pop;

  5. Вставка значения х в вершину стека (элемент заталкивается в стек) — операция Push.

Операция Сreate представляет собой примитивный конструктор, операция IsNull — индикатор, GetTop — селектор, операции Push и Pop — модификаторы.

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

Спецификацию каждой операции представим в виде:

операция: множество входных данных  множество выходных данных

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

Пусть стек состоит из элементов типа α. Введем новый тип данных  Stack of α  Stack ( α ). Непустой стек обозначим как Non_null_stack.

Базовый набор операций определяется так:

  1. Create:  Stack ( α ) ;

  2. IsNull:  Stack ( α )  Boolean ;

  3. GetTop:   Non_null_stack ( α )  α ;

  4. Pop:  Non_null_stack ( α )  Stack ( α ) ;

  5. Push:   α  Stack ( α )  Stack ( α )

Дополним данное определение набором аксиом, которые справедливы для вышеуказанных операций. Пусть p — значение типа α; s —stack ( α ):

A1. IsNull ( Create ) = true ;

A2. IsNull ( Push ( p , s ) ) = false ;

A3. GetTop ( Push ( p , s ) ) = p ;

A4. Pop ( Push ( p , s ) ) = s ;

A5. Push ( GetTop ( s ) , Pop ( s ) ) = s.

Часто при определении стека вместо операции Pop используют операцию, совмещающую результат действия GetTop и Pop. Обозначим такую операцию Pop2. Тогда

Pop2:  Non_null_stack ( α )  α  Stack ( α ).