Стеки, очереди и деки

Содержание

Слайд 2

План лекции Стеки Очереди Деки

План лекции

Стеки
Очереди
Деки

Слайд 3

Стеки, очереди и деки Это такие динамические структуры, представляющие собой списки,

Стеки, очереди и деки

Это такие динамические структуры, представляющие собой списки, для

которых разрешены только операции вставки и удаления первого и/или последнего элемента.
Слайд 4

Стеки

Стеки

Слайд 5

Стек Стек - извлечение и добавление элементов в нем происходит по

Стек

Стек - извлечение и добавление элементов в нем происходит по правилу «Последний

пришел, первый вышел» (LIFO — last in, first out). Добавление и извлечение элементов проводится с головы.
Слайд 6

Стек Стек – это упорядоченный набор элементов, в котором добавление новых

Стек

Стек – это упорядоченный набор элементов, в котором добавление новых и

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

На рисунке показан стек, содержащий 6 элементов.

Слайд 7

Стек В современных компьютерах стек используется для: размещения локальных переменных; размещения

Стек

В современных компьютерах стек используется для:
размещения локальных переменных;
размещения параметров процедуры или

функции;
сохранения адреса возврата (по какому адресу надо вернуться из процедуры);
временного хранения данных, особенно при программировании на Ассемблере.
Слайд 8

Стек На стек выделяется ограниченная область памяти. При каждом вызове функции

Стек

На стек выделяется ограниченная область памяти. При каждом вызове функции в

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

Стек Стек - это двухсвязный список, в котором разрешены только операции

Стек

Стек - это двухсвязный список, в котором разрешены только операции добавления

нового элемента в голову списка и удаление элемента с головы списка, согласно принципу LIFO.

Стек можно реализовать на основе двухсвязного списка

Узел1

Узел2

Узел3

Голова
списка

Хвост
списка

Слайд 10

Стек Для работы со стеком надо определить, как выполняются две операции

Стек

Для работы со стеком надо определить, как выполняются две операции –

добавление элемента на вершину стека (Push) и снятие элемента с вершины стека (Pop). При этом количество элементов стека ограничивается толь-
ко доступным объемом памяти.

Узел1

Узел2

Узел3

Голова
списка

Хвост
списка

Слайд 11

struct Node { Тип1 поле1; Тип2 поле2; ….. Node *next; Node

struct Node
{
Тип1 поле1;
Тип2 поле2;
…..
Node *next;

Node *prev;
};
typedef Node * PNode;

Синтаксис объявления стека в С++:

Стек

В программе надо объявить два новых типа данных – узел списка Node и указатель на него PNode.

Чтобы не работать с отдельными указателями на хвост и голову списка, объявим структуру, в
которой будет храниться вся информация о стеке:

struct Stack
{
PNode Head, Tail;
};

Слайд 12

struct Node { string word; Node *next; Node *prev; }; typedef

struct Node
{
string word;
Node *next;
Node *prev;
};
typedef Node

*PNode;
struct Stack
{
PNode Head, Tail;
};
Stack S;
S.Head = NULL;
S.Tail = NULL;

Пример. Объявление стека словаря:

Стек

Например, опишем стек для представления словаря русских слов.

Слайд 13

Стеки. Операции Операции над стеком: Добавление нового узла в список –

Стеки. Операции

Операции над стеком:

Добавление нового узла в список – операция Push
Извлечение

(удаление) узла из списка – операция Pop

Push

Pop

Слайд 14

Создание нового узла Для стека мы не будем отдельно создавать функцию

Создание нового узла

Для стека мы не будем отдельно создавать функцию для

создания нового узла, которая включала только выделение памяти под новый узел и запоминание адреса выделенного блока, так как у нас нет возможности вставлять узел в произвольное место списка.
В стеке новый узел можно вставить только в начало списка, поэтому объединим вместе две операции CreateNode и AddFirst.
Также немного переделаем листинг кода, чтобы работать не с отдельными указателями, а со структурой типа Stack.

Создание нового узла


PNode NewNode = new Node;
NewNode->word = NewWord;
NewNode->next = NULL;
NewNode->prev = NULL;
return NewNode;

Слайд 15

Добавление узла на вершину стека При добавлении нового узла NewNode на

Добавление узла на вершину стека

При добавлении нового узла NewNode на вершину

стека надо:

2) установить ссылку next узла NewNode на голову существующего списка и его ссылку prev в NULL;

NewNode->next = Head;
NewNode->prev= NULL;

3) установить ссылку prev бывшего первого узла (если он существовал) на NewNode;

if ( Head!=NULL )
Head->prev = NewNode;

4) установить голову списка на новый узел;

5) если в списке не было ни одного элемента, хвост списка также устанавливается на новый узел.

Head = NewNode;

if ( Tail == NULL ) Tail = Head;

создать новый узел

Слайд 16

Добавление узла на вершину стека void Push ( Stack &S, string

Добавление узла на вершину стека

void Push ( Stack &S, string data

)
{
PNode NewNode;
NewNode = new Node;
NewNode->word = data;
NewNode->next = S.Head;
NewNode->prev = NULL;
if ( S.Head !=NULL)
S.Head->prev = NewNode;
  S.Head = NewNode;
if ( S.Tail ==NULL)
S.Tail = S.Head;
}

// функция добавления нового узла в стек

Важно, что адрес стека передаётся по ссылке

Алгоритм создания нового узла

Алгоритм добавления нового узла в начало двухсвязного списка

Слайд 17

Снятие (удаление узла) с вершины стека Функция Pop удаляет верхний элемент

Снятие (удаление узла) с вершины стека

Функция Pop удаляет верхний элемент и

возвращает его данные.

Pop

Эта операция идентична операции удаления узла из двухсвязного списка, но только при условии что он является первым.
Адрес OldNode нам передавать не нужно, так как мы знаем, что он первый

Слайд 18

4) Рассмотрим только один случай если удаляемый элемент является первым!! 5)

4) Рассмотрим только один случай
если удаляемый элемент
является первым!!

5) Проверяем ,

это был единственный элемент или нет. Если голова не пустая,
то устанавливаем предыдущую ссылку головы, а иначе все пусто!

S.Head = TopNode->next;

6) Освобождаем память, которую занимал узел.

delete TopNode;

Снятие (удаление узла) с вершины стека

if ( S.Head != NULL )
S.Head->prev = NULL;
else S.Tail = NULL;
}

PNode TopNode = S.Head;

Узнаем адрес первого узла

2) Если список пустой, то выведем сообщение и выходим из функции

if ( TopNode==NULL )
return “Список пустой”;

data = TopNode->word;

3) Сохраняем данные об узле

7) Выводим данные о узле

return data;

Слайд 19

Снятие узла с вершины стека string Pop ( Stack &S )

Снятие узла с вершины стека

string Pop ( Stack &S )
{
PNode TopNode

= S.Head;
string data;
if ( TopNode==NULL )
return “Список пустой”;
data = TopNode->word;
S.Head = TopNode->next;
if ( S.Head != NULL )
S.Head->prev = NULL;
else
S.Tail = NULL;
delete TopNode;
return data;
}

// удаляем первый элемент

// изменяем ссылки головы

// освобождаем память

// Алгоритм удаления узла из списка, а
именно удаляем единственный элемент

// удаляем последний элемент

// возвращение данных, чтобы вывести
информацию о узле, который удалили

// если список пустой, то выведем сообщение и выходим из функции

// встали на начало списка

// иначе сохранили данные

Слайд 20

Вывод всех элементов стека void Print ( Stack &S ) {

Вывод всех элементов стека

void Print ( Stack &S )
{
PNode TopNode

= S.Head;
while (TopNode != NULL)
{
cout<word< TopNode=TopNode->next;
}
}

// переходим к следующему узлу

// Обход списка с головы списка

// начинаем с вершины стека

// пока не дошли до конца

// выводим данные узла

Слайд 21

Поиск узла в списке Часто требуется найти в списке нужный элемент

Поиск узла в списке

Часто требуется найти в списке нужный элемент (его

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

1) начать с головы списка;

2) пока текущий элемент существует (указатель – не NULL), проверить нужное условие и перейти к следующему элементу;

3) закончить, когда найден
требуемый элемент или все элементы списка
просмотрены.

Поиск по данным

PNode q = S.Head;

while (q->word != NewWord && q!=NULL)
q = q->next;

return q;

Слайд 22

Поиск узла в списке PNode Find (Stack S, string NewWord) {

Поиск узла в списке

PNode Find (Stack S, string NewWord)
{
PNode q

= S.Head;
while (q->word != NewWord && q != NULL)
q = q->next;
return q;
}

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

// функция поиска узла в списке

//начать с головы списка

//пока текущий элемент существует
(указатель – не NULL), проверить
нужное условие и перейти к
следующему элементу

Например, следующая функция ищет в списке элемент, соответствующий заданному слову (для которого поле word совпадает с заданной строкой NewWord), и возвращает его адрес или NULL, если такого узла нет.

Слайд 23

Очередь

Очередь

Слайд 24

Очередь Очередь - список, операции чтения и добавления элементов в котором

Очередь

Очередь - список, операции чтения и добавления элементов в котором подвержены правилу

«Первый пришел, первый вышел» (FIFO — first in, first out) .
При этом, при чтении элемента, он удаляется из очереди. Таким образом, для чтения в очереди доступна только голова, в то время как добавление проводится только в хвост.
Слайд 25

Очередь Очередь – это упорядоченный набор элементов, в котором добавление новых

Очередь

Очередь – это упорядоченный набор элементов, в котором добавление новых элементов

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

Очередь Очередь называют структурой типа FIFO (First In – First Out)

Очередь

Очередь называют структурой типа FIFO (First In – First Out) –

первым пришел, первым ушел. Хорошо знакомой моделью является очередь в магазине. На рисунке изображена очередь из 3-х элементов.
Слайд 27

Очередь Наиболее известные примеры применения очередей в программировании – очередь событий

Очередь

Наиболее известные примеры применения очередей в программировании – очередь событий системы

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

Очередь Очередь - это двухсвязный список, в котором разрешены только операции

Очередь

Очередь - это двухсвязный список, в котором разрешены только операции добавления

нового элемента в хвост списка и удаление элемента с головы списка, согласно принципу FIFO.

Очередь можно реализовать на основе двухсвязного списка

Узел1

Узел2

Узел3

Голова
списка

Хвост
списка

Слайд 29

Очередь Для работы с очередью надо определить, как выполняются две операции

Очередь

Для работы с очередью надо определить, как выполняются две операции –

добавление элемента в конец очереди (Push) и снятие (удаление) элемента с головы списка (Pop).

Узел1

Узел2

Узел3

Голова
списка

Хвост
списка

Слайд 30

struct Node { Тип1 поле1; Тип2 поле2; ….. Node *next; Node

struct Node
{
Тип1 поле1;
Тип2 поле2;
…..
Node *next;

Node *prev;
};
typedef Node * PNode;

Синтаксис объявления очереди в С++:

Очередь

В программе надо объявить два новых типа данных – узел списка Node и указатель на него PNode.

Чтобы не работать с отдельными указателями на хвост и голову списка, объявим структуру, в
которой будет храниться вся информация о очереди:

struct Queue
{
PNode Head, Tail;
};

Слайд 31

struct Node { string word; Node *next; Node *prev; }; typedef

struct Node
{
string word;
Node *next;
Node *prev;
};
typedef Node

*PNode;
struct Queue
{
PNode Head, Tail;
};
Queue Q;
Q.Head = NULL;
Q.Tail = NULL;

Пример. Объявление очереди словаря:

Очередь

Например, опишем очередь для представления словаря русских слов.

Слайд 32

Очередь. Операции Операции над очередью: Добавление нового узла в конец очереди

Очередь. Операции

Операции над очередью:

Добавление нового узла в конец очереди – операция

Push
Извлечение (удаление) узла с начала очереди – операция Pop

Push

Pop

Слайд 33

Добавление узла в очередь Фактически это добавление нового элемента в конец

Добавление узла в очередь

Фактически это добавление нового элемента в конец двусвязного

списка. Объединим две операции создание нового узла и добавление в конец списка.

2) установить ссылку prev узла NewNode на хвост существующего списка и его ссылку next в NULL;

NewNode->prev = Tail;
NewNode->next = NULL;

3) установить ссылку next бывшего конечного узла (если он существовал) на NewNode;

if ( Tail!=NULL )
Tail->next = NewNode;

4) установить хвост списка на новый узел;

5) если в списке не было ни одного элемента, голову списка также устанавливается на новый узел.

Tail = NewNode;

if ( Head == NULL )
Head = Tail;

Создать новый узел

Слайд 34

Добавление узла в конец очереди void Push (Queue &Q, string data

Добавление узла в конец очереди

void Push (Queue &Q, string data )


{
PNode NewNode;
NewNode = new Node;
NewNode->word = data;
NewNode->prev = Q.Tail;
NewNode->next = NULL;
if ( Q.Tail != NULL )
Q.Tail->next = NewNode;
Q.Tail = NewNode;
  if (Q.Head == NULL) Q.Head = Q.Tail;
}

// функция добавления нового узла в очередь

Важно, что адрес очереди передаётся по ссылке

Алгоритм создания нового узла

Алгоритм добавления нового узла в конец двухсвязного списка

Слайд 35

Снятие (удаление узла) с начала очереди Функция Pop удаляет верхний элемент

Снятие (удаление узла) с начала очереди

Функция Pop удаляет верхний элемент и

возвращает его данные.

Pop

Более того, функция для получения первого элемента очереди (Pop) совпадает с функцией снятия элемента с вершины стека.

Слайд 36

4) Рассмотрим только один случай если удаляемый элемент является первым!! 5)

4) Рассмотрим только один случай
если удаляемый элемент
является первым!!

5) Проверяем ,

это был единственный элемент или нет. Если голова не пустая,
то устанавливаем предыдущую ссылку головы, а иначе все пусто!

Q.Head = TopNode->next;

6) Освобождаем память, которую занимал узел.

delete TopNode;

Снятие (удаление узла) с начала очереди

if ( Q.Head != NULL )
Q.Head->prev = NULL;
else Q.Tail = NULL;
}

PNode TopNode = Q.Head;

Узнаем адрес первого узла

2) Если список пустой, то выведем сообщение и выходим из функции

if ( TopNode==NULL )
return “Список пустой”;

data = TopNode->word;

3) Сохраняем данные об узле

7) Выводим данные о узле

return data;

Слайд 37

Снятие узла с головы очереди string Pop (Queue &Q ) {

Снятие узла с головы очереди

string Pop (Queue &Q )
{
PNode TopNode =

Q.Head;
string data;
if ( TopNode==NULL )
return “Список пустой”;
data = TopNode->word;
Q.Head = TopNode->next;
if ( Q.Head != NULL )
Q.Head->prev = NULL;
else
Q.Tail = NULL;
delete TopNode;
return data;
}

// удаляем первый элемент

// изменяем ссылки головы

// освобождаем память

// Алгоритм удаления узла из списка, а
именно удаляем единственный элемент

// удаляем последний элемент

// возвращение данных, чтобы вывести
информацию о узле, который удалили

// если список пустой, то выведем сообщение и выходим из функции

// встали на начало списка

// иначе сохранили данные

Слайд 38

Вывод всех элементов очереди void Print (Queue &Q ) { PNode

Вывод всех элементов очереди

void Print (Queue &Q )
{
PNode TopNode =

Q.Head;
while (TopNode != NULL)
{
cout<word< TopNode=TopNode->next;
}
}

// переходим к следующему узлу

// Обход списка с головы списка

// начинаем с вершины очереди

// пока не дошли до конца

// выводим данные узла

Слайд 39

Дек

Дек

Слайд 40

Дек Дек (deque) - это упорядоченный набор элементов, в котором добавление

Дек

Дек (deque) - это упорядоченный набор элементов, в котором добавление новых

и удаление существующих элементов допустимо с любого конца.
Слайд 41

Дек Дек может быть реализован на основе двусвязного списка. Для дека

Дек

Дек может быть реализован на основе двусвязного списка. Для дека разрешены

четыре операции:
1) добавление элемента в начало;
2) добавление элемента в конец;
3) удаление элемента с начала;
4) удаление элемента с конца.
Их можно реализовать, используя написанные выше функции для стека и очереди.
Слайд 42

Спасибо за внимание!

Спасибо за внимание!