SlideShare une entreprise Scribd logo
1  sur  43
Télécharger pour lire hors ligne
Лекция 3

Стеки и очереди
Курносов Михаил Георгиевич
к.т.н. доцент Кафедры вычислительных систем
Сибирский государственный университет
телекоммуникаций и информатики

http://www.mkurnosov.net/teaching
Стек (Stack)
 Стек (Stack) – структура данных для хранения элементов
 Дисциплина доступа к элементам:
“последним пришел – первым вышел” (Last In – First Out, LIFO)
 Элементы помещаются и извлекаются с головы стека (top)
D

D

Pop

Push
Top

D
C
B
A

2
Подходы к реализации стека
1. На основе связных списков (linked lists)
Длина стека ограничена объемом доступной памяти
2. На основе статических массивов
Длина стека фиксирована (задана его максимальная
длина – количество элементов в массиве)

4
Реализация стека на основе связных списков
 Элементы стека хранятся в односвязном списке
(singly linked list)

 Добавление элемент и удаление выполняется
за время O(1)
Stack:
Size

Top

Данные

Next

Данные

Next

Данные

Next

NULL

5
Реализация стека на основе связных списков
#include <stdio.h>
#include <stdlib.h>
#include "llist.h"
struct stack {
struct listnode *top;
int size;
};

/* см. лекцию 3 */

/* Верхушка стека */

6
Реализация стека на основе связных списков
/*
* Фрагмент файла llist.c
*/
struct listnode {
int value;

/* Данные стека */

struct listnode *next;
};
7
Реализация стека на основе связных списков
/* stack_create: Creates an empty stack */
struct stack *stack_create()
{
struct stack *s = malloc(sizeof(*s));
if (s != NULL) {
s->size = 0;
s->top = NULL;
}
return s;
TCreate = O(1)
}

8
Реализация стека на основе связных списков
/* stack_free: Removes stack */
void stack_free(struct stack *s)
{
while (s->size > 0)
stack_pop(s);
/* Delete All items */
free(s);
TFree = O(n)
}
Stack:
Size

Top

Данные

Next

Данные

Next

Данные

Next

NULL

9
Реализация стека на основе связных списков
/* stack_size: Returns size of a stack */
int stack_size(struct stack *s)
{
return s->size;
TSize = O(1)
}

10
Реализация стека на основе связных списков
int main()
{
struct stack *s;
s = stack_create();
printf("Stack size: %dn", stack_size(s));
stack_free(s);
return 0;
}

11
Реализация стека на основе связных списков
/* stack_push: Pushes item to the stack */
int stack_push(struct stack *s, int value)
{
s->top = list_addfront(s->top, value);
if (s->top == NULL) {
fprintf(stderr,
"stack: Stack overflown");
return -1;
}
s->size++;
return 0;
TPush = O(1)
}
12
Реализация стека на основе связных списков
/* stack_pop: Pops item from the stack */
int stack_pop(struct stack *s)
{
struct listnode *next;
int value;
if (s->top == NULL) {
fprintf(stderr, "stack: Stack underflown");
return -1;
}
next = s->top->next;
value = s->top->value;
free(s->top);
s->top = next;
s->size--;
return value;
}

TPop = O(1)
13
Реализация стека на основе связных списков
int main()
{
struct stack *s;
int i, val;
s = stack_create();
for (i = 1; i <= 10; i++) {
stack_push(s, i);
}
for (i = 1; i <= 11; i++) {
val = stack_pop(s);
printf("pop: %dn", val);
}
stack_free(s);

pop:
pop:
pop:
pop:
pop:
pop:
pop:
pop:
pop:
pop:
pop:

10
9
8
7
6
5
4
3
2
1
-1

return 0;
}
14
Реализация стека на основе массива
 Элементы стека хранятся в массиве фиксированной
длины L
 Добавление элемент и удаление выполняется
за время O(1)

L–1
…
Top

2

C

1

B

0

A
15
Реализация стека на основе массива
#include <stdio.h>
#include <stdlib.h>
struct stack {
int *v;
int top;
int size;
int maxsize;
};
16
Реализация стека на основе массива
/* stack_create: Creates an empty stack */
struct stack *stack_create(int maxsize)
{
struct stack *s = malloc(sizeof(*s));
if (s != NULL) {
s->v = malloc(sizeof(int) * maxsize);
if (s->v == NULL) {
free(s);
return NULL;
}
s->size = 0;
s->top = 0;
s->maxsize = maxsize;
}
return s;
TCreate = O(1)
}
17
Реализация стека на основе массива
/* stack_free: Removes stack */
void stack_free(struct stack *s)
{
free(s->v);
free(s);
}

TFree = O(1)

/* stack_size: Returns size of a stack */
int stack_size(struct stack *s)
{
return s->size;
TSize = O(1)
}
18
Реализация стека на основе массива
/* stack_push: Pushes item to the stack */
int stack_push(struct stack *s, int value)
{
if (s->top < s->maxsize) {
s->v[s->top++] = value;
s->size++;
} else {
fprintf(stderr, "stack: Stack overflown");
return -1;
}
return 0;
TPush = O(1)
}

19
Реализация стека на основе массива
/* stack_pop: Pops item from the stack */
int stack_pop(struct stack *s)
{
if (s->top == 0) {
fprintf(stderr,
"stack: Stack underflown");
return -1;
}
s->size--;
return s->v[--s->top];
TPop = O(1)
}

20
Очередь (Queue)
 Очередь (Queue) – структура данных для хранения элементов
(контейнер)
 Дисциплина доступа к элементам:
“первым пришел – первым вышел” (First In – First Out, FIFO)

 Элементы добавляются в хвост (tail), извлекаются с головы (head)

Кит

Enqueue

Back
(tail, rear)
Слон

Front
(head)
Жираф

Волк

Заяц

Dequeue

Рысь

21
Очередь (Queue)
 Очереди широко используется в алгоритмах обработки
данных:
 очереди печати

 буфер ввода с клавиатуры
 алгоритмы работы с графами

22
Очередь (Queue)
Операция

Описание

Enqueue(q, x)

Добавляет элемент x в очередь q

Dequeue(q)

Извлекает элемент из очереди q

Size(q)

Возвращает количество элементов в
очереди q

Clear(q)

Очищает очередь q

23
Подходы к реализации очереди
1. На основе связных списков
Длина очереди ограничена лишь объемом
доступной памяти
2. На основе статических массивов
Длина очереди фиксирована (задана максимальная
длина)

24
Реализация очереди на основе связных списков
 Элементы очереди хранятся в односвязном списке
(singly linked list)
 Для быстрого (за время O(1)) добавления и извлечения
элементов из списка поддерживается указатель на
последний элемент (tail)
 Новые элементы добавляются в конец списка
Queue:
Size

Head

Данные

Tail

Next

Данные

Next

Данные

Next

NULL

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

Queue:
Size

Head

Данные

Tail

Next

Данные

Next

Данные

Next

NULL

26
Реализация очереди на основе связных списков
#include <stdio.h>
#include <stdlib.h>
#include "llist.h"
struct queue {
struct listnode *head;
struct listnode *tail;
int size;
};

27
Реализация очереди на основе связных списков
/* queue_create: Creates an empty queue */
struct queue *queue_create()
{
struct queue *q = malloc(sizeof(*q));
if (q != NULL) {
q->size = 0;
q->head = NULL;
q->tail = NULL;
}
return q;
TCreate = O(1)
}

28
Реализация очереди на основе связных списков
/* queue_free: Removes queue */
void queue_free(struct queue *q)
{
while (q->size > 0)
queue_dequeue(q);
free(q);
TFree = O(n)
}

29
Реализация очереди на основе связных списков
/* queue_size: Returns size of a queue */
int queue_size(struct queue *q)
{
TSize = O(1)
return q->size;
}
int main()
{
struct queue *q;
q = queue_create();
queue_free(q);
return 0;

}
30
Реализация очереди на основе связных списков
/* queue_enqueue: Add item to the queue */
void queue_enqueue(struct queue *q, int value)
{
struct listnode *oldtail = q->tail;
/* Create new node */
q->tail = list_createnode(value);
if (q->head == NULL) {
/* List is empty */
q->head = q->tail;
} else {
/* Add new node to the end of list */
oldtail->next = q->tail;
}
q->size++;
}

TEnqueue = O(1)
31
Реализация очереди на основе связных списков
int main()
{
struct queue *q;
int i;
q = queue_create();
for (i = 1; i <= 10; i++) {
queue_enqueue(q, i);
}
printf("Queue size: %dn", queue_size(q));
queue_free(q);
return 0;
}
32
Реализация очереди на основе связных списков
/* queue_dequeue: Gets item from the queue */
int queue_dequeue(struct queue *q)
{
int value;
struct listnode *p;
if (q->size == 0)
return -1;
/* Delete first node */
value = q->head->value;
p = q->head->next;
free(q->head);
q->head = p;
q->size--;
return value;
}

TDequeue = O(1)
33
Реализация очереди на основе связных списков
int main()
{
struct queue *q;
int i, j;
q = queue_create();
/* ... */
for (i = 1; i <= 11; i++) {
j = queue_dequeue(q);
printf("%d: next element: %dn", i, j);
}
queue_free(q);
return 0;
}
34
Реализация очереди на основе циклических массивов
 Элементы очереди хранятся в массиве фиксированной
длины [0..L – 1]

 Массив логически представляется в виде кольца
(circular buffer)
 В пустой очереди Tail = 0, Head = L

0

1

2

L–1

L

X
Tail

Head
35
Реализация очереди на основе циклических массивов
 При добавлении элемента в очередь значение Tail
циклически увеличивается на 1
(сдвигается на следующую свободную позицию)
 Если Head = Tail + 1, то очередь переполнена!
Enqueue(1):
0

1

1

2

3

L–1

L

X
Tail

Head
36
Реализация очереди на основе циклических массивов
 При удалении возвращается элемент с номером Head % L
 Значение Head циклически увеличивается на 1
(указывает на следующий элемент очереди)
0

1

2

3

L–1

1

L

X
Head

Tail

Dequeue():
0
1

2

3

L–1

L

X
Head

Tail

37
Реализация очереди на основе циклических массивов
#include <stdio.h>
#include <stdlib.h>
struct queue {
int *v;
int head;
int tail;
int size;
int maxsize;
};

38
Реализация очереди на основе циклических массивов
/* queue_create: Creates an empty queue */
struct queue *queue_create(int maxsize)
{
struct queue *q = malloc(sizeof(*q));
if (q != NULL) {
q->v = malloc(sizeof(int) * (maxsize + 1));
if (q->v == NULL) {
free(q);
return NULL;
}
q->maxsize = maxsize;
q->size = 0;
q->head = maxsize + 1;
q->tail = 0;
}
return q;
TCreate = O(1)
}
39
Реализация очереди на основе циклических массивов
/* queue_free: Removes queue */
void queue_free(struct queue *q)
{
free(q->v);
free(q);
}

/* queue_size: Returns size of a queue */
int queue_size(struct queue *q)
{
return q->size;
}
40
Реализация очереди на основе циклических массивов
/* queue_enqueue: Add item to the queue */
int queue_enqueue(struct queue *q, int value)
{
if (q->head == q->tail + 1) {
fprintf(stderr,
"queue: Queue overflown");
return -1;
}
q->v[q->tail++] = value;
q->tail = q->tail % (q->maxsize + 1);
q->size++;
return 0;
}

TEnqueue = O(1)
41
Реализация очереди на основе циклических массивов
/* queue_dequeue: Gets item from the queue */
int queue_dequeue(struct queue *q)
{
if (q->head % (q->maxsize + 1) == q->tail)
{
/* Queue is empty */
fprintf(stderr,
"queue: Queue is emptyn");
return -1;
}
q->head = q->head % (q->maxsize + 1);
q->size--;
return q->v[q->head++];

}

TDequeue = O(1)
42
Реализация очереди на основе циклических массивов
int main()
{
struct queue *q;
int i, val;
q = queue_create(10);
val = queue_dequeue(q);
for (i = 1; i <= 11; i++) {
queue_enqueue(q, i);
}
for (i = 1; i <= 5; i++) {
val = queue_dequeue(q);
}
queue_free(q);
return 0;
}
43
Домашнее чтение
 Найти и прочитать о двухсторонней очереди
(дек, deque – double ended queue)

44

Contenu connexe

Tendances

Лекция 2: Абстрактные типы данных. Алгоритмы сортировки
Лекция 2: Абстрактные типы данных. Алгоритмы сортировкиЛекция 2: Абстрактные типы данных. Алгоритмы сортировки
Лекция 2: Абстрактные типы данных. Алгоритмы сортировки
Mikhail Kurnosov
 
Лекция 10: Графы. Остовные деревья минимальной стоимости
Лекция 10: Графы. Остовные деревья минимальной стоимостиЛекция 10: Графы. Остовные деревья минимальной стоимости
Лекция 10: Графы. Остовные деревья минимальной стоимости
Mikhail Kurnosov
 
Алгоритмы и структуры данных весна 2014 лекция 1
Алгоритмы и структуры данных весна 2014 лекция 1Алгоритмы и структуры данных весна 2014 лекция 1
Алгоритмы и структуры данных весна 2014 лекция 1
Technopark
 

Tendances (20)

Игорь Кудрин, «Используем неизменяемые данные и создаем качественный код»
Игорь Кудрин, «Используем неизменяемые данные и создаем качественный код»Игорь Кудрин, «Используем неизменяемые данные и создаем качественный код»
Игорь Кудрин, «Используем неизменяемые данные и создаем качественный код»
 
Лекция 4. Префиксные деревья (tries, prefix trees)
Лекция 4. Префиксные деревья (tries, prefix trees)Лекция 4. Префиксные деревья (tries, prefix trees)
Лекция 4. Префиксные деревья (tries, prefix trees)
 
Лекция 11. Методы разработки алгоритмов
Лекция 11. Методы разработки алгоритмовЛекция 11. Методы разработки алгоритмов
Лекция 11. Методы разработки алгоритмов
 
Лекция 1. Анализ эффективности алгоритмов
Лекция 1. Анализ эффективности алгоритмовЛекция 1. Анализ эффективности алгоритмов
Лекция 1. Анализ эффективности алгоритмов
 
Лекция 2: Абстрактные типы данных. Алгоритмы сортировки
Лекция 2: Абстрактные типы данных. Алгоритмы сортировкиЛекция 2: Абстрактные типы данных. Алгоритмы сортировки
Лекция 2: Абстрактные типы данных. Алгоритмы сортировки
 
Основы SciPy
Основы SciPyОсновы SciPy
Основы SciPy
 
Лекция 10. Графы. Остовные деревья минимальной стоимости
Лекция 10. Графы. Остовные деревья минимальной стоимостиЛекция 10. Графы. Остовные деревья минимальной стоимости
Лекция 10. Графы. Остовные деревья минимальной стоимости
 
Лекция 10: Графы. Остовные деревья минимальной стоимости
Лекция 10: Графы. Остовные деревья минимальной стоимостиЛекция 10: Графы. Остовные деревья минимальной стоимости
Лекция 10: Графы. Остовные деревья минимальной стоимости
 
Векторизация кода (семинар 2)
Векторизация кода (семинар 2)Векторизация кода (семинар 2)
Векторизация кода (семинар 2)
 
Python. Объектно-ориентированное программирование
Python. Объектно-ориентированное программирование Python. Объектно-ориентированное программирование
Python. Объектно-ориентированное программирование
 
Лекция 7. Стандарт OpenMP (подолжение)
Лекция 7. Стандарт OpenMP (подолжение)Лекция 7. Стандарт OpenMP (подолжение)
Лекция 7. Стандарт OpenMP (подолжение)
 
Лекция 2. Алгоритмы сортировки
Лекция 2. Алгоритмы сортировкиЛекция 2. Алгоритмы сортировки
Лекция 2. Алгоритмы сортировки
 
Векторизация кода (семинар 3)
Векторизация кода (семинар 3)Векторизация кода (семинар 3)
Векторизация кода (семинар 3)
 
Основы NumPy
Основы NumPyОсновы NumPy
Основы NumPy
 
Лекция 10. Биномиальные кучи (Binomial heaps)
Лекция 10. Биномиальные кучи (Binomial heaps)Лекция 10. Биномиальные кучи (Binomial heaps)
Лекция 10. Биномиальные кучи (Binomial heaps)
 
Лекция 8. Графы. Обходы графов
Лекция 8. Графы. Обходы графовЛекция 8. Графы. Обходы графов
Лекция 8. Графы. Обходы графов
 
Основы языка Питон: типы данных, операторы
Основы языка Питон: типы данных, операторыОсновы языка Питон: типы данных, операторы
Основы языка Питон: типы данных, операторы
 
Алгоритмы и структуры данных весна 2014 лекция 1
Алгоритмы и структуры данных весна 2014 лекция 1Алгоритмы и структуры данных весна 2014 лекция 1
Алгоритмы и структуры данных весна 2014 лекция 1
 
Основы Python. Функции
Основы Python. ФункцииОсновы Python. Функции
Основы Python. Функции
 
Григорий Демченко, “Асинхронность и сопрограммы: обработка данных“
Григорий Демченко, “Асинхронность и сопрограммы: обработка данных“Григорий Демченко, “Асинхронность и сопрограммы: обработка данных“
Григорий Демченко, “Асинхронность и сопрограммы: обработка данных“
 

Similaire à Лекция 4: Стеки и очереди

C++ осень 2012 лекция 11
C++ осень 2012 лекция 11C++ осень 2012 лекция 11
C++ осень 2012 лекция 11
Technopark
 
Scala and LiftWeb presentation (Russian)
Scala and LiftWeb presentation (Russian)Scala and LiftWeb presentation (Russian)
Scala and LiftWeb presentation (Russian)
Dmitry Stropalov
 
Лекция №5. Линейные структуры данных. Предмет "Структуры и алгоритмы обработк...
Лекция №5. Линейные структуры данных. Предмет "Структуры и алгоритмы обработк...Лекция №5. Линейные структуры данных. Предмет "Структуры и алгоритмы обработк...
Лекция №5. Линейные структуры данных. Предмет "Структуры и алгоритмы обработк...
Nikolay Grebenshikov
 
Алгоритмы и структуры данных осень 2013 лекция 2
Алгоритмы и структуры данных осень 2013 лекция 2Алгоритмы и структуры данных осень 2013 лекция 2
Алгоритмы и структуры данных осень 2013 лекция 2
Technopark
 
Школа-студия разработки приложений для iOS. Лекция 1. Objective-C
Школа-студия разработки приложений для iOS. Лекция 1. Objective-CШкола-студия разработки приложений для iOS. Лекция 1. Objective-C
Школа-студия разработки приложений для iOS. Лекция 1. Objective-C
Глеб Тарасов
 
Лекция 12 (часть 2): Языки программирования семейства PGAS: IBM X10
Лекция 12 (часть 2): Языки программирования семейства PGAS: IBM X10Лекция 12 (часть 2): Языки программирования семейства PGAS: IBM X10
Лекция 12 (часть 2): Языки программирования семейства PGAS: IBM X10
Mikhail Kurnosov
 

Similaire à Лекция 4: Стеки и очереди (20)

Лекция 3 Элементарные структуры данных Часть 1
Лекция 3 Элементарные структуры данных Часть 1Лекция 3 Элементарные структуры данных Часть 1
Лекция 3 Элементарные структуры данных Часть 1
 
Лекция 8. Intel Threading Building Blocks
Лекция 8. Intel Threading Building BlocksЛекция 8. Intel Threading Building Blocks
Лекция 8. Intel Threading Building Blocks
 
C++ осень 2012 лекция 11
C++ осень 2012 лекция 11C++ осень 2012 лекция 11
C++ осень 2012 лекция 11
 
01 линейные структуры данных
01 линейные структуры данных01 линейные структуры данных
01 линейные структуры данных
 
лек9 10
лек9 10лек9 10
лек9 10
 
Scala and LiftWeb presentation (Russian)
Scala and LiftWeb presentation (Russian)Scala and LiftWeb presentation (Russian)
Scala and LiftWeb presentation (Russian)
 
Лекция №5. Линейные структуры данных. Предмет "Структуры и алгоритмы обработк...
Лекция №5. Линейные структуры данных. Предмет "Структуры и алгоритмы обработк...Лекция №5. Линейные структуры данных. Предмет "Структуры и алгоритмы обработк...
Лекция №5. Линейные структуры данных. Предмет "Структуры и алгоритмы обработк...
 
Алгоритмы и структуры данных осень 2013 лекция 2
Алгоритмы и структуры данных осень 2013 лекция 2Алгоритмы и структуры данных осень 2013 лекция 2
Алгоритмы и структуры данных осень 2013 лекция 2
 
Школа-студия разработки приложений для iOS. Лекция 1. Objective-C
Школа-студия разработки приложений для iOS. Лекция 1. Objective-CШкола-студия разработки приложений для iOS. Лекция 1. Objective-C
Школа-студия разработки приложений для iOS. Лекция 1. Objective-C
 
ПВТ - весна 2015 - Лекция 4. Шаблоны многопоточного программирования
ПВТ - весна 2015 - Лекция 4. Шаблоны многопоточного программированияПВТ - весна 2015 - Лекция 4. Шаблоны многопоточного программирования
ПВТ - весна 2015 - Лекция 4. Шаблоны многопоточного программирования
 
Лекция 12 (часть 2): Языки программирования семейства PGAS: IBM X10
Лекция 12 (часть 2): Языки программирования семейства PGAS: IBM X10Лекция 12 (часть 2): Языки программирования семейства PGAS: IBM X10
Лекция 12 (часть 2): Языки программирования семейства PGAS: IBM X10
 
ПВТ - весна 2015 - Лекция 5. Многопоточное программирование в С++. Синхрониза...
ПВТ - весна 2015 - Лекция 5. Многопоточное программирование в С++. Синхрониза...ПВТ - весна 2015 - Лекция 5. Многопоточное программирование в С++. Синхрониза...
ПВТ - весна 2015 - Лекция 5. Многопоточное программирование в С++. Синхрониза...
 
Быстрые конструкции в Python - Олег Шидловский, Python Meetup 26.09.2014
Быстрые конструкции в Python - Олег Шидловский, Python Meetup 26.09.2014Быстрые конструкции в Python - Олег Шидловский, Python Meetup 26.09.2014
Быстрые конструкции в Python - Олег Шидловский, Python Meetup 26.09.2014
 
ПВТ - осень 2014 - Лекция 5 - Многопоточное программирование в языке С++. Р...
ПВТ - осень 2014 - Лекция 5 - Многопоточное программирование в языке С++.   Р...ПВТ - осень 2014 - Лекция 5 - Многопоточное программирование в языке С++.   Р...
ПВТ - осень 2014 - Лекция 5 - Многопоточное программирование в языке С++. Р...
 
лекция 3
лекция 3лекция 3
лекция 3
 
Дмитрий Прокопцев — R-ссылки в С++11
Дмитрий Прокопцев — R-ссылки в С++11Дмитрий Прокопцев — R-ссылки в С++11
Дмитрий Прокопцев — R-ссылки в С++11
 
Sergii Tsypanov "Performance 1001 Tips"
Sergii Tsypanov "Performance 1001 Tips"Sergii Tsypanov "Performance 1001 Tips"
Sergii Tsypanov "Performance 1001 Tips"
 
ПВТ - весна 2015 - Лекция 6. Разработка параллельных структур данных на основ...
ПВТ - весна 2015 - Лекция 6. Разработка параллельных структур данных на основ...ПВТ - весна 2015 - Лекция 6. Разработка параллельных структур данных на основ...
ПВТ - весна 2015 - Лекция 6. Разработка параллельных структур данных на основ...
 
Lisp8
Lisp8Lisp8
Lisp8
 
Lisp8
Lisp8Lisp8
Lisp8
 

Plus de Mikhail Kurnosov

Plus de Mikhail Kurnosov (20)

Векторизация кода (семинар 1)
Векторизация кода (семинар 1)Векторизация кода (семинар 1)
Векторизация кода (семинар 1)
 
Лекция 7. Декартовы деревья (Treaps, дучи, дерамиды)
Лекция 7. Декартовы деревья (Treaps, дучи, дерамиды)Лекция 7. Декартовы деревья (Treaps, дучи, дерамиды)
Лекция 7. Декартовы деревья (Treaps, дучи, дерамиды)
 
Лекция 6. Стандарт OpenMP
Лекция 6. Стандарт OpenMPЛекция 6. Стандарт OpenMP
Лекция 6. Стандарт OpenMP
 
Лекция 5. Основы параллельного программирования (Speedup, Amdahl's law, Paral...
Лекция 5. Основы параллельного программирования (Speedup, Amdahl's law, Paral...Лекция 5. Основы параллельного программирования (Speedup, Amdahl's law, Paral...
Лекция 5. Основы параллельного программирования (Speedup, Amdahl's law, Paral...
 
Лекция 5. B-деревья (B-trees, k-way merge sort)
Лекция 5. B-деревья (B-trees, k-way merge sort)Лекция 5. B-деревья (B-trees, k-way merge sort)
Лекция 5. B-деревья (B-trees, k-way merge sort)
 
Лекция 4. Векторизация кода (Code vectorization: SSE, AVX)
Лекция 4. Векторизация кода (Code vectorization: SSE, AVX)Лекция 4. Векторизация кода (Code vectorization: SSE, AVX)
Лекция 4. Векторизация кода (Code vectorization: SSE, AVX)
 
Лекция 3. Оптимизация доступа к памяти (Memory access optimization, cache opt...
Лекция 3. Оптимизация доступа к памяти (Memory access optimization, cache opt...Лекция 3. Оптимизация доступа к памяти (Memory access optimization, cache opt...
Лекция 3. Оптимизация доступа к памяти (Memory access optimization, cache opt...
 
Лекция 3. АВЛ-деревья (AVL trees)
Лекция 3. АВЛ-деревья (AVL trees)Лекция 3. АВЛ-деревья (AVL trees)
Лекция 3. АВЛ-деревья (AVL trees)
 
Лекция 2. Оптимизация ветвлений и циклов (Branch prediction and loop optimiz...
Лекция 2. Оптимизация ветвлений и циклов (Branch prediction and loop optimiz...Лекция 2. Оптимизация ветвлений и циклов (Branch prediction and loop optimiz...
Лекция 2. Оптимизация ветвлений и циклов (Branch prediction and loop optimiz...
 
Лекция 2. Красно-чёрные деревья (Red-black trees). Скошенные деревья (Splay t...
Лекция 2. Красно-чёрные деревья (Red-black trees). Скошенные деревья (Splay t...Лекция 2. Красно-чёрные деревья (Red-black trees). Скошенные деревья (Splay t...
Лекция 2. Красно-чёрные деревья (Red-black trees). Скошенные деревья (Splay t...
 
Лекция 1. Амортизационный анализ (amortized analysis)
Лекция 1. Амортизационный анализ (amortized analysis)Лекция 1. Амортизационный анализ (amortized analysis)
Лекция 1. Амортизационный анализ (amortized analysis)
 
Семинар 12. Параллельное программирование на MPI (часть 5)
Семинар 12. Параллельное программирование на MPI (часть 5)Семинар 12. Параллельное программирование на MPI (часть 5)
Семинар 12. Параллельное программирование на MPI (часть 5)
 
Семинар 11. Параллельное программирование на MPI (часть 4)
Семинар 11. Параллельное программирование на MPI (часть 4)Семинар 11. Параллельное программирование на MPI (часть 4)
Семинар 11. Параллельное программирование на MPI (часть 4)
 
Семинар 10. Параллельное программирование на MPI (часть 3)
Семинар 10. Параллельное программирование на MPI (часть 3)Семинар 10. Параллельное программирование на MPI (часть 3)
Семинар 10. Параллельное программирование на MPI (часть 3)
 
Семинар 9. Параллельное программирование на MPI (часть 2)
Семинар 9. Параллельное программирование на MPI (часть 2)Семинар 9. Параллельное программирование на MPI (часть 2)
Семинар 9. Параллельное программирование на MPI (часть 2)
 
Лекция 9. Поиск кратчайшего пути в графе
Лекция 9. Поиск кратчайшего пути в графеЛекция 9. Поиск кратчайшего пути в графе
Лекция 9. Поиск кратчайшего пути в графе
 
Семинар 8. Параллельное программирование на MPI (часть 1)
Семинар 8. Параллельное программирование на MPI (часть 1)Семинар 8. Параллельное программирование на MPI (часть 1)
Семинар 8. Параллельное программирование на MPI (часть 1)
 
Семинар 7. Многопоточное программирование на OpenMP (часть 7)
Семинар 7. Многопоточное программирование на OpenMP (часть 7)Семинар 7. Многопоточное программирование на OpenMP (часть 7)
Семинар 7. Многопоточное программирование на OpenMP (часть 7)
 
Семинар 6. Многопоточное программирование на OpenMP (часть 6)
Семинар 6. Многопоточное программирование на OpenMP (часть 6)Семинар 6. Многопоточное программирование на OpenMP (часть 6)
Семинар 6. Многопоточное программирование на OpenMP (часть 6)
 
Лекция 6. Хеш-таблицы
Лекция 6. Хеш-таблицыЛекция 6. Хеш-таблицы
Лекция 6. Хеш-таблицы
 

Лекция 4: Стеки и очереди

  • 1. Лекция 3 Стеки и очереди Курносов Михаил Георгиевич к.т.н. доцент Кафедры вычислительных систем Сибирский государственный университет телекоммуникаций и информатики http://www.mkurnosov.net/teaching
  • 2. Стек (Stack)  Стек (Stack) – структура данных для хранения элементов  Дисциплина доступа к элементам: “последним пришел – первым вышел” (Last In – First Out, LIFO)  Элементы помещаются и извлекаются с головы стека (top) D D Pop Push Top D C B A 2
  • 3. Подходы к реализации стека 1. На основе связных списков (linked lists) Длина стека ограничена объемом доступной памяти 2. На основе статических массивов Длина стека фиксирована (задана его максимальная длина – количество элементов в массиве) 4
  • 4. Реализация стека на основе связных списков  Элементы стека хранятся в односвязном списке (singly linked list)  Добавление элемент и удаление выполняется за время O(1) Stack: Size Top Данные Next Данные Next Данные Next NULL 5
  • 5. Реализация стека на основе связных списков #include <stdio.h> #include <stdlib.h> #include "llist.h" struct stack { struct listnode *top; int size; }; /* см. лекцию 3 */ /* Верхушка стека */ 6
  • 6. Реализация стека на основе связных списков /* * Фрагмент файла llist.c */ struct listnode { int value; /* Данные стека */ struct listnode *next; }; 7
  • 7. Реализация стека на основе связных списков /* stack_create: Creates an empty stack */ struct stack *stack_create() { struct stack *s = malloc(sizeof(*s)); if (s != NULL) { s->size = 0; s->top = NULL; } return s; TCreate = O(1) } 8
  • 8. Реализация стека на основе связных списков /* stack_free: Removes stack */ void stack_free(struct stack *s) { while (s->size > 0) stack_pop(s); /* Delete All items */ free(s); TFree = O(n) } Stack: Size Top Данные Next Данные Next Данные Next NULL 9
  • 9. Реализация стека на основе связных списков /* stack_size: Returns size of a stack */ int stack_size(struct stack *s) { return s->size; TSize = O(1) } 10
  • 10. Реализация стека на основе связных списков int main() { struct stack *s; s = stack_create(); printf("Stack size: %dn", stack_size(s)); stack_free(s); return 0; } 11
  • 11. Реализация стека на основе связных списков /* stack_push: Pushes item to the stack */ int stack_push(struct stack *s, int value) { s->top = list_addfront(s->top, value); if (s->top == NULL) { fprintf(stderr, "stack: Stack overflown"); return -1; } s->size++; return 0; TPush = O(1) } 12
  • 12. Реализация стека на основе связных списков /* stack_pop: Pops item from the stack */ int stack_pop(struct stack *s) { struct listnode *next; int value; if (s->top == NULL) { fprintf(stderr, "stack: Stack underflown"); return -1; } next = s->top->next; value = s->top->value; free(s->top); s->top = next; s->size--; return value; } TPop = O(1) 13
  • 13. Реализация стека на основе связных списков int main() { struct stack *s; int i, val; s = stack_create(); for (i = 1; i <= 10; i++) { stack_push(s, i); } for (i = 1; i <= 11; i++) { val = stack_pop(s); printf("pop: %dn", val); } stack_free(s); pop: pop: pop: pop: pop: pop: pop: pop: pop: pop: pop: 10 9 8 7 6 5 4 3 2 1 -1 return 0; } 14
  • 14. Реализация стека на основе массива  Элементы стека хранятся в массиве фиксированной длины L  Добавление элемент и удаление выполняется за время O(1) L–1 … Top 2 C 1 B 0 A 15
  • 15. Реализация стека на основе массива #include <stdio.h> #include <stdlib.h> struct stack { int *v; int top; int size; int maxsize; }; 16
  • 16. Реализация стека на основе массива /* stack_create: Creates an empty stack */ struct stack *stack_create(int maxsize) { struct stack *s = malloc(sizeof(*s)); if (s != NULL) { s->v = malloc(sizeof(int) * maxsize); if (s->v == NULL) { free(s); return NULL; } s->size = 0; s->top = 0; s->maxsize = maxsize; } return s; TCreate = O(1) } 17
  • 17. Реализация стека на основе массива /* stack_free: Removes stack */ void stack_free(struct stack *s) { free(s->v); free(s); } TFree = O(1) /* stack_size: Returns size of a stack */ int stack_size(struct stack *s) { return s->size; TSize = O(1) } 18
  • 18. Реализация стека на основе массива /* stack_push: Pushes item to the stack */ int stack_push(struct stack *s, int value) { if (s->top < s->maxsize) { s->v[s->top++] = value; s->size++; } else { fprintf(stderr, "stack: Stack overflown"); return -1; } return 0; TPush = O(1) } 19
  • 19. Реализация стека на основе массива /* stack_pop: Pops item from the stack */ int stack_pop(struct stack *s) { if (s->top == 0) { fprintf(stderr, "stack: Stack underflown"); return -1; } s->size--; return s->v[--s->top]; TPop = O(1) } 20
  • 20. Очередь (Queue)  Очередь (Queue) – структура данных для хранения элементов (контейнер)  Дисциплина доступа к элементам: “первым пришел – первым вышел” (First In – First Out, FIFO)  Элементы добавляются в хвост (tail), извлекаются с головы (head) Кит Enqueue Back (tail, rear) Слон Front (head) Жираф Волк Заяц Dequeue Рысь 21
  • 21. Очередь (Queue)  Очереди широко используется в алгоритмах обработки данных:  очереди печати  буфер ввода с клавиатуры  алгоритмы работы с графами 22
  • 22. Очередь (Queue) Операция Описание Enqueue(q, x) Добавляет элемент x в очередь q Dequeue(q) Извлекает элемент из очереди q Size(q) Возвращает количество элементов в очереди q Clear(q) Очищает очередь q 23
  • 23. Подходы к реализации очереди 1. На основе связных списков Длина очереди ограничена лишь объемом доступной памяти 2. На основе статических массивов Длина очереди фиксирована (задана максимальная длина) 24
  • 24. Реализация очереди на основе связных списков  Элементы очереди хранятся в односвязном списке (singly linked list)  Для быстрого (за время O(1)) добавления и извлечения элементов из списка поддерживается указатель на последний элемент (tail)  Новые элементы добавляются в конец списка Queue: Size Head Данные Tail Next Данные Next Данные Next NULL 25
  • 25. Реализация очереди на основе связных списков  Преимущества: длина очереди ограничена лишь объемом доступной памяти  Недостатки (по сравнению с реализацией на основе массивов): работа с очередью немного медленнее, требуется больше памяти для хранения одного элемента Queue: Size Head Данные Tail Next Данные Next Данные Next NULL 26
  • 26. Реализация очереди на основе связных списков #include <stdio.h> #include <stdlib.h> #include "llist.h" struct queue { struct listnode *head; struct listnode *tail; int size; }; 27
  • 27. Реализация очереди на основе связных списков /* queue_create: Creates an empty queue */ struct queue *queue_create() { struct queue *q = malloc(sizeof(*q)); if (q != NULL) { q->size = 0; q->head = NULL; q->tail = NULL; } return q; TCreate = O(1) } 28
  • 28. Реализация очереди на основе связных списков /* queue_free: Removes queue */ void queue_free(struct queue *q) { while (q->size > 0) queue_dequeue(q); free(q); TFree = O(n) } 29
  • 29. Реализация очереди на основе связных списков /* queue_size: Returns size of a queue */ int queue_size(struct queue *q) { TSize = O(1) return q->size; } int main() { struct queue *q; q = queue_create(); queue_free(q); return 0; } 30
  • 30. Реализация очереди на основе связных списков /* queue_enqueue: Add item to the queue */ void queue_enqueue(struct queue *q, int value) { struct listnode *oldtail = q->tail; /* Create new node */ q->tail = list_createnode(value); if (q->head == NULL) { /* List is empty */ q->head = q->tail; } else { /* Add new node to the end of list */ oldtail->next = q->tail; } q->size++; } TEnqueue = O(1) 31
  • 31. Реализация очереди на основе связных списков int main() { struct queue *q; int i; q = queue_create(); for (i = 1; i <= 10; i++) { queue_enqueue(q, i); } printf("Queue size: %dn", queue_size(q)); queue_free(q); return 0; } 32
  • 32. Реализация очереди на основе связных списков /* queue_dequeue: Gets item from the queue */ int queue_dequeue(struct queue *q) { int value; struct listnode *p; if (q->size == 0) return -1; /* Delete first node */ value = q->head->value; p = q->head->next; free(q->head); q->head = p; q->size--; return value; } TDequeue = O(1) 33
  • 33. Реализация очереди на основе связных списков int main() { struct queue *q; int i, j; q = queue_create(); /* ... */ for (i = 1; i <= 11; i++) { j = queue_dequeue(q); printf("%d: next element: %dn", i, j); } queue_free(q); return 0; } 34
  • 34. Реализация очереди на основе циклических массивов  Элементы очереди хранятся в массиве фиксированной длины [0..L – 1]  Массив логически представляется в виде кольца (circular buffer)  В пустой очереди Tail = 0, Head = L 0 1 2 L–1 L X Tail Head 35
  • 35. Реализация очереди на основе циклических массивов  При добавлении элемента в очередь значение Tail циклически увеличивается на 1 (сдвигается на следующую свободную позицию)  Если Head = Tail + 1, то очередь переполнена! Enqueue(1): 0 1 1 2 3 L–1 L X Tail Head 36
  • 36. Реализация очереди на основе циклических массивов  При удалении возвращается элемент с номером Head % L  Значение Head циклически увеличивается на 1 (указывает на следующий элемент очереди) 0 1 2 3 L–1 1 L X Head Tail Dequeue(): 0 1 2 3 L–1 L X Head Tail 37
  • 37. Реализация очереди на основе циклических массивов #include <stdio.h> #include <stdlib.h> struct queue { int *v; int head; int tail; int size; int maxsize; }; 38
  • 38. Реализация очереди на основе циклических массивов /* queue_create: Creates an empty queue */ struct queue *queue_create(int maxsize) { struct queue *q = malloc(sizeof(*q)); if (q != NULL) { q->v = malloc(sizeof(int) * (maxsize + 1)); if (q->v == NULL) { free(q); return NULL; } q->maxsize = maxsize; q->size = 0; q->head = maxsize + 1; q->tail = 0; } return q; TCreate = O(1) } 39
  • 39. Реализация очереди на основе циклических массивов /* queue_free: Removes queue */ void queue_free(struct queue *q) { free(q->v); free(q); } /* queue_size: Returns size of a queue */ int queue_size(struct queue *q) { return q->size; } 40
  • 40. Реализация очереди на основе циклических массивов /* queue_enqueue: Add item to the queue */ int queue_enqueue(struct queue *q, int value) { if (q->head == q->tail + 1) { fprintf(stderr, "queue: Queue overflown"); return -1; } q->v[q->tail++] = value; q->tail = q->tail % (q->maxsize + 1); q->size++; return 0; } TEnqueue = O(1) 41
  • 41. Реализация очереди на основе циклических массивов /* queue_dequeue: Gets item from the queue */ int queue_dequeue(struct queue *q) { if (q->head % (q->maxsize + 1) == q->tail) { /* Queue is empty */ fprintf(stderr, "queue: Queue is emptyn"); return -1; } q->head = q->head % (q->maxsize + 1); q->size--; return q->v[q->head++]; } TDequeue = O(1) 42
  • 42. Реализация очереди на основе циклических массивов int main() { struct queue *q; int i, val; q = queue_create(10); val = queue_dequeue(q); for (i = 1; i <= 11; i++) { queue_enqueue(q, i); } for (i = 1; i <= 5; i++) { val = queue_dequeue(q); } queue_free(q); return 0; } 43
  • 43. Домашнее чтение  Найти и прочитать о двухсторонней очереди (дек, deque – double ended queue) 44