Стеки деки очереди деревья

Простейшие структуры данных: стек, очередь, дек

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

По определению, структура данных — способ представления данных в памяти, позволяющий эффективно выполнять с ними определённый набор операций. Например, простой массив лучше всего подходит для частого обращения к элементам по индексам и их изменению. А удаление элемента из середины массива работает за \(O(N)\). Если вам для решения задачи нужно часто удалять элементы, то придётся воспользоваться другой структурой данной. Например, бинарное дерево ( std::set ) позволяет делать это за \(O(\log N)\), но не поддерживает работу с индексами, только поочерёдный обход всех элементов и поиск по значению (тоже за \(O(\log N)\)).

Таким образом, структура данных характеризуется операциями, которые она может выполнять, и скоростью их выполнения.

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

Стек

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

  • Добавить элемент в стек (Сложность: \(O(1)\))
  • Извлечь элемент из стека (Сложность: \(O(1)\))
  • Проверить, пуст ли стек (Сложность: \(O(1)\))

Для объяснения принципа работы стека часто используется аналогия со стаканом с печеньем. Представьте, что на дне вашего стакана лежат несколько кусков печенья. Вы можете положить наверх ещё один кусок или достать уже находящийся наверху. Остальные куски закрыты верхним, и вы про них ничего не знаете. Для описания стека часто используется аббревиатура LIFO (Last In, First Out), подчёркивающая, что элемент, попавший в стек последним, первым будет из него извлечён.

Читайте также:  Фактура дерева разделочные доски

Приведём простую реализацию стека на C++. Для простоты максимальный размер нашего стека будет ограничен тысячей элементов:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
struct stack  int a[1000]; int head = -1; //Индекс крайнего элемента. void push(int x)  head++; a[head] = x; > int pop()  if (head != -1)  head--; return a[head + 1]; > else  //Ошибка, попытка извлечь элемент из пустого стека. > > bool is_empty()  return head == -1; > >; 

Как видите, для реализации стека хватает одного массива и одного указателя, обозначающего крайний элемент.

Очередь

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

Реализация очереди похожа на реализацию стека, но в этот раз нам понадобятся два указателя: для первого элемента очереди (“головы”) и последнего (“хвоста”):

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
struct queue  int a[1000]; //Для более лаконичной реализации работы, мы будем //хранить указатель не на последний элемент, а //на следующий за ним (несуществующий). //Это, в частности, позволит нам проверять очередь на пустоту //простым условием head == tail int head = 0; //Индекс первого элемента. int tail = 0; //Индекс элемента, следующего за последним. void push(int x)  a[tail] = x; tail++; > int pop()  if (head != tail)  head++; return a[head - 1]; > else  //Ошибка, попытка извлечь элемент из пустой очереди. > > bool is_empty()  return head == tail; > >; 

При такой реализации очередь будет постепенно “ползти” вправо по выделенной области памяти (массиву), и достаточно быстро выйдет за её границы. Впрочем, эта реализация иллюстративная, на практике вы просто будете использовать уже готовую реализацию очереди из стандартной библиотеки (об этом ниже). В ней этот дефект отсутствует из-за более сложной работы с памятью.

Дек

Структура, объединяющая стек и очередь, называется дек (англ. deque - сокращение от double-ended queue, очередь с двумя концами). Как можно догадаться, она поддерживает уже знакомый набор операций:

  • Добавить элемент в начало дека (Сложность: \(O(1)\))
  • Извлечь элемент из начала дека (Сложность: \(O(1)\))
  • Добавить элемент в конец дека (Сложность: \(O(1)\))
  • Извлечь элемент из конца дека (Сложность: \(O(1)\))
  • Проверить, пуст ли дек (Сложность: \(O(1)\))

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

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40
struct deque  int a[2000]; //Используя такие начальные значения индексов, у нас //будет свободная память как слева, так и справа. int head = 1000; //Индекс первого элемента. int tail = 1000; //Индекс элемента, следующего за последним. void push_front(int x)  head--; a[head] = x; > void push_back(int x)  a[tail] = x; tail++; > int pop_front()  if (head != tail)  head++; return a[head - 1]; > else  //Ошибка, попытка извлечь элемент из пустого дека. > > int pop_back()  if (head != tail)  tail--; return a[tail]; > else  //Ошибка, попытка извлечь элемент из пустого дека. > > bool is_empty()  return head == tail; > >; 

Стек, очередь и дек в стандартной библиотеке C++

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

stackint> s; //создание стека s.push(5); //добавление элемента cout  <s.top(); //обращение к верхнему элементу if (!s.empty())  //проверка на пустоту s.pop(); //извлечение элемента (не возвращает значения, //нужно предварительно использовать .top()) > queueint> q; //создание очереди q.push(5); //добавление элемента cout  <q.front()  <' '  <q.back(); //обращение к первому и последнему элементам if (!q.empty())  //проверка на пустоту q.pop(); //извлечение элемента (не возвращает значения, //нужно предварительно использовать .top()) > 

С реализацией дека дела обстоят несколько иначе. Стандартный класс std::deque является не классическим деком, а скорее вектором с возможностью вставки и добавления в начало за \(O(1)\). Он поддерживает все операции, поддерживаемые классом std::vector , в том числе обращение к элементу по индексу и итераторы с произвольным доступом. Так что для работы с ним используйте те же методы, что и при работе с вектором.

Более сложные структуры данных

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

brestprog

Олимпиадное программирование в Бресте и Беларуси

Источник

Презентация, доклад Динамические структуры данных. Стек, очередь, дек, деревья

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

Динамические структуры данныхСтек Стеком называется динамическая структура данных, добавление компоненты в которую иСтек Использование стека в программировании: Нужно сохранить некоторую работу, котораяСтек Использование стека в программировании: используются при разборе (parsing) грамматикСтекСтекСтекСтекСтекСтекСтекСтекСтекСтекСтекСтекОчередьОчередьОчередьОчередьОчередьОчередьОчередь. Добавление элементаОчередь. Добавление элементаОчередь. Извлечение элементаОчередь. Очистка очередиДек Дек является симбиозом стека и очереди - это та жеГрафДеревья Деревом называют конечный связный граф с выделенной вершиной (корнем), неДеревья Для каждой пары вершин дерева – узлов – существует единственныйДеревья Висячие вершины, за исключением корневой, называются листьями. Число путейБинарные деревья Деревья, в которых каждый узел либо является листом, либоБинарные деревья Ключевые термины: Бинарное (двоичное) дерево – это дерево, вБинарные деревья Ключевые термины: Листья дерева – это вершины, в которыеБинарные деревья Ключевые термины: Полное бинарное дерево – это дерево, котороеБинарные деревья Ключевые термины: Степень вершины – это количество дуг, котороеБинарные деревья В программировании при решении большого класса задач используются бинарныеБинарные деревья Описание бинарного дерева выглядит следующим образом: struct имя_типа < Бинарные деревьяБинарные деревьяБинарные деревьяБинарные деревьяБинарные деревьяБинарные деревьяБинарные деревьяБинарные дере</p><p><span class=Источник

Оцените статью