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

2.2.2. Ссылочная реализация стека в динамической памяти

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

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

Рис.2.2. Ссылочная реализация стека с помощью списка в динамической памяти

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

Для вставки необходимо:

  • захватить память под новый элемент, заполнить данными содержательную часть;

  • указующей части присвоить значение указателя на вершину;

  • присвоить указателю на вершину адрес нового элемента (он теперь будет вершиной).

Для извлечения элемента:

  • запомнить в буфере данные, хранящиеся в последнем элементе;

  • освободить память, которую занимал последний элемент;

  • изменить указатель на вершину стека (теперь вершиной будет предпослений элемент);

  • возвратить последний элемент из буфера.

В листинге 2.2 приведена реализация стека. Также, как и в реализации на массиве, используем структуру stack, в которую включаем указатель top на вершину и набор функций для реализации базовых операций со стеком. В данном листинге демонстрируется использование шаблонов.

Листинг 2.2. Реализация стека с помощью указателей

#include <stdlib.h>

#include <iostream.h>

template <class T> // шаблонный тип тип элементов

struct item //структура каждого элемента стека

{ T data; // данные

item<T> *prev; // указатель на предыдущий элемент

};

template <class T>

struct stack //структура стека, включающая операции

{ item<T> *top;

stack() {top=NULL;} //конструктор, выполняется //автоматически при создании стека

void push (T x); // поместить значение x в стек

T pop();// извлечь элемент с вершины стека

T gettop();// получить вершину стека

bool isnull() {return top==NULL;} // проверка на пустоту

void makenull(); //сделать стек пустым

};

template <class T> void stack<T>::push(T x)

{ item<T> *p=new item<T>; p->data=x; p->prev=top; // добавили //элемент

top=p; // изменили указател на вершину top

}

template <class T> T stack<T>::pop ()

{ if (isnull()) {cerr<< "Стек пуст \n"; exit(1);}; // //аварийная ситуация

T d=top->data; // запомнили данные последнего элемента

item<T> *p=top; top=top->prev; delete p; // удалили элемент и изменили top

return d; // возвратили данные

}

template <class T> void stack<T>::makenull()

{ while (top) pop(); // удаляем элементы по очереди

}

template <class T> T stack<T>::gettop()

{return top->data;}

При использовании данной реализации описание конкретного стека с элементами, например, типа char, будет иметь вид

stack<char> имя;

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