Линейные структуры данных и стандартная библиотека шаблонов

advertisement
Линейные структуры данных и
стандартная библиотека
шаблонов
Тенчурин Д.Р.
271ПИ
Линейные структуры данных
Линейные структуры — это упорядоченные
структуры, в которых адрес элемента
однозначно определяется его номером.
Линейных структуры данных обладают
следующими свойствами:
 Каждый элемент имеет не более 1
предшественника
 Два разных элемента не могут иметь
одинакового последователя
Линейные структуры данных
К линейным структурам данным можно
отнести:
◦ Массивы
 Динамические массивы
◦
◦
◦
◦
◦
Связный список
Стек
Очередь
Дек
Хэш-таблица
Массивы
Массив – одна из простейших и наиболее широко
применяемых в компьютерных программах линейных
структур данных. В любом языке программирования
массивы имеют несколько общих свойств:
 Содержимое массива хранится в непрерывной области
памяти.
 Все элементы массива имеют одинаковый тип; поэтому
массивы называют однородными структурами данных.
 Существует прямой доступ к элементам массива.
Типичные операции для массивов включают:
• Выделение элемента(Allocation)
• Доступ к элементу (Accessing)
• Изменение размеров массива (Redimensioning)
Строки

В языке C строки было принято
представлять в виде массива символов:
В языке C++ для представления строки
используется класс string
 Обе структуры линейны, но вторую
принято считать более удобной,
безопасной и простой в использовании

Класс String
#include <string>
Поддерживает операции:
Удаления посл-ти символов (erase)
Поиска подстроки (find)
Возврата подстроки (substr)
Замены подстроки (replace)
Вставки подстроки (insert)
Стандартная библиотека
шаблонов STL
Предоставляет обобщенные
компоненты для решения задач
Условно можно разделить на 3 части:
 Контейнеры
 Итераторы
 Алгоритмы
Контейнеры STL
Контейнеры в STL – обобщенный
классы, моделирующие различные
структуры данных
 Например:

◦ #include <hash_set>
◦ #include <hash_map>
◦ #include <slist>
Контейнеры STL








#include <string> // строки
#include <vector> // динамический массив
#include <list> // двусвязный список
#include <deque> // дек
#include <queue> // очередь
#include <stack> // стэк
#include <set> // множество
#include <map> // ассоциативный список
Итераторы
Итераторы – интерфейс между
контейнерами и алгоритмами.
 Итератор - это универсальный способ
доступа к элементам контейнера.
 Ведет себя как указатель.
 Пример:

string A = "This is a string";
string::iterator it; // создание итератора
for (it = A.begin(); it != A.end(); ++it) {
cout << *it << endl;
}
Алгоритмы
Реализованы как свободные функции,
а не члены-функции
 Использование - #include <algorithm>
 Все алгоритмы работают с
итераторами на контейнерах
 Для корректной работы –
использование пространства имен std

Использование Vector
Vector – динамически расширяемый
массив
 Объявление – vector<type> v();
 Доступ к элементам – так же как в
массиве, сложность O(1)
 Добавление элемента – O(1) в конец,
O(n) в других случаях
 Поиск O(n)

Дек
С точки зрения программиста –
использование схоже с Vector
 Отличие в реализации – Vector – это
массив, когда как для удобство
добавления элемента Deque
реализован как множество массивов

Использование Дека

// Предикат

bool is_odd(int i) {
◦ return ((i % 2) == 1);

}

int main(int argc, char* argv[]) {
◦ deque<int> numbers;
◦ for (int i = 0; i < 20; i++) {
 numbers.push_back(i);
◦ }
◦ cout << count(numbers.begin(), numbers.end(), 10) << endl;
◦ cout << count_if(numbers.begin(), numbers.end(), is_odd)
◦ << endl;
◦ return EXIT_SUCCESS;

}
Связные списки

Связный список - это разновидность линейных структур
данных, представляющая собой последовательность
элементов, обычно отсортированную в соответствии с
заданным правилом. Последовательность может
содержать любое количество элементов, поскольку при
создании
списка
используется
динамическое
распределение памяти.

Каждый элемент связного списка представляет собой
отдельный объект, содержащий поле для хранения
информации и указатель на следующий элемент списка
(а в случае двусвязного списка в объекте хранится также
указатель на предыдущий элемент).
Использование list
Объявление - list<int> l1;
Добавление элемента – O(n) в худшем случае
// Добавить элемент после 1ого
list<int> l(10);
list<int>::iterator it = l.begin();
it++;
l.insert(it, 5);
Удаление элемента – O(n) в худшем случае
// Удаление второго элемента
list<int> l(10);
list<int>::iterator second = l.begin();
second++;
l.erase(second);
Поиск – О(n)
Очередь
Очередь – линейная структура данных,
удовлетворяющая принципу FIFO
(первый пришел – первый ушел)
 Поддерживает добавление элемента в
конец, доступ к первому и последнему,
удаление первого элемента
 Не поддерживает итераторы

Очередь - Пример

queue<int> q;

// добавить и удалить

q.push(1);

q.pop();

// доступ к первому и последнему

q.push(1);

q.push(2);

cout << q.front() << endl;

cout << q.back() << endl;

// размер

cout << q.size() << endl;

cout << q.empty() << endl;
Стек
Очередь – линейная структура данных,
удовлетворяющая принципу
FILO(первый пришел – последний
ушел)
 Поддерживает добавление элемента в
конец, доступ к первому и последнему,
удаление последнего элемента

Стек-Пример

stack<int> s;

// Добавление и удаление элемента из вершины стека

s.push(1);

s.pop();

// Доступ к вершине стека

s.push(10);

s.push(11);

cout << s.top() << endl;

// Размер

cout << s.size() << endl;

cout << s.empty() << endl;
Download