Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
САОД_ответы_catsto_NEW.doc
Скачиваний:
17
Добавлен:
16.04.2019
Размер:
365.57 Кб
Скачать
  1. Ассоциативные и последовательные контейнеры stl. Понятие итератора. Общие свойства контейнеров. Особенности и применение каждого из контейнеров.

Важную роль в программировании играют так называемые абстрактные типы данных или контейнеры – классы, служащие для хранения других типов данных. Стандартная библиотека C++ (STL) предоставляет ряд эффективных контейнеров. Все они реализованы в виде шаблонов и конкретные типы можно строить, параметризуя шаблон типом элементов, которые будет содержать контейнер.

Контейнеры STL можно параметризовать любыми типами, для которых определены операции «=», «= =», «<».

Одно из важных свойств контейнеров STL заключается в создании копии при включении в контейнер. Если какой либо объект помещается в контейнер, то помещается не он сам, а его копия. Таким образом, если объекты класса не могут копироваться dummy конструктором копии, то необходимо создавать конструктор копии для такого класса.

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

С точки зрения использования итератор выглядит как указатель. Допустим, мы определили некоторый контейнер типа <TYPE NAME>. Тогда итератор для этого контейнера объявляется как <TYPE NAME>::integrator i. Если мы имеем объект контейнера obj типа <TYPE NAME>, то можно установить итератор на первый элемент контейнера:

<TYPE NAME>::iterator i = obj.begin();

*i в таком случае будет означать элемент контейнера, на который указывает итератор, в нашем случае первый элемент. i++ позволяет перейти к следующему элементу, хранящемуся в контейнере, а сравнение итератора с obj.end() позволяет выяснить, закончились ли элементы контейнера. Таким образом, задача прохода по всем элементам контейнера может быть записана так:

for(<TYPE NAME>::iterator i = obj.begin(); i != obj.end(); i++)

// Do what you need with element using *I ;

Отличия итератора от индексации:

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

- Индексация не подходит для всех структур данных, в частности, для структур данных, с медленным произвольным доступом или вообще без поддержки такового (например, список или дерево).

- Итераторы обеспечивают способ последовательного перебора любых структур данных, поэтому делают код более читаемым, удобным для повторного использования и менее чувствительным к изменениям структур данных.

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

- Итератор позволяет модифицировать объекты контейнера без влияния нам сам итератор. Например, после того, как итератор уже «прошёл» первый элемент, можно вставить дополнительные элементы в начало контейнера без каких-либо нежелательных последствий. При использовании индексации это весьма проблематично из-за смены индексных номеров.

Общие свойства контейнеров:

- не зависит от n (количества элементов), как массив.

- поместить в контейнер, то есть поместить туда копию объекта.

- универсальный проход по контейнеру (с помощью итератора)

Последовательные контейнеры:

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

Список

Рассмотрим работу со списком на примере списка строк. Список очень эффективен при изменении структуры (вставке, удалении элементов) и не эффективен при поиске.

//define new type

typedef list<string> LSTSTR;

//create lists

LSTSTR lst1, lst2(5, “abc”); //empty lst1 and lst2 with 5 elements

LSTSTR lst3(lst2), lst4(lst2.begin(), --lst2.end());

//check if list is empty

cout << lst1.empty() << endl; //true

//add elements

lst1.push_back(“2”); lst1.push_front(“1”); // list is {1,2}

lst1.insert(--lst1.end(), “a”); // list is {1,a,2}

cout << lst1.size() << endl; // 3

//modify existing element

*lst1.begin() = “3”; // list is {3,a,2}

//access first/last elements

cout << lst1.front() << endl; //3

cout << lst1.back() << endl; //2

//assign one list to another

lst2 = lst1;

//remove elements

lst1.remove(“a”); // list is {3,2}

lst1.erase(lst1.begin()) // list is {2}

lst1.erase(lst1.end()) // list is empty

Отсортировать список можно методом sort.

lst2.sort() // list is {2, 3, a}

Динамический массив

Рассмотрим вектор целых чисел:

//define new type

typedef vector<int> VINT;

//create vectors