
Лекция-2.09.ppt
- Количество слайдов: 26
C++ standard library Associative containers set multiset map multimap Лекция 17 -21. 04. 2014 г. 1
Ассоциативные контейнеры – это упорядоченные коллекции, обеспечивающие быстрый поиск данных, основанных на ключах. Каждый элемент ассоциативного контейнера занимает определенную позицию, которая связана со значением его ключа и не зависит от времени и места вставки. Все ассоциативные контейнеры используют в качестве параметров Key (ключ) и упорядочивающее отношение Compare, которое вызывает полное упорядочение по элементам Key. Кроме того, map и multimap ассоциируют (связывают) данные произвольного типа с ключом. Объект типа Compare называется сравнивающим объектом (comparison object) контейнера. Лекция 17 -21. 04. 2014 г. 2
Ассоциативные контейнеры Поддержка работы с ассоциативными контейнерами представлена в заголовочных файлах: set – содержит определение шаблонных классов set и multiset, а также определение внешней шаблонной функции swap и перегруженных шаблонных операций: ==, !=, <, <=, >, >= map – содержит определение шаблонных классов map и multimap, а также определение внешней шаблонной функции swap и перегруженных шаблонных операций: ==, !=, <, <=, >, >= Лекция 17 -21. 04. 2014 г. 3
Замечания по поводу реализации (внутреннего устройства) ассоциативных контейнеров Ассоциативные контейнеры реализованы в форме красно-черных деревьев. Красно-чёрное дерево (Red-Black-Tree, RB-Tree) — это одно из самобалансирующихся двоичных деревьев поиска, гарантирующих логарифмический рост высоты дерева от числа узлов и быстро выполняющее основные операции дерева поиска: добавление, удаление и поиск узла. Сбалансированность достигается за счёт введения дополнительного атрибута узла дерева — «цвета» . Этот атрибут может принимать одно из двух возможных значений — «чёрный» или «красный» . Лекция 17 -21. 04. 2014 г. 4
Ассоциативные контейнеры В контейнере set (множество) хранятся уникальные элементы, следующие в определенном порядке. Значение элемента множества также идентифицирует сам элемент (т. е. значение является ключом). Значения элементов в контейнере set не могут быть изменены (т. е. элементы обладают свойством const), но элементы могут быть вставлены или удалены из контейнера. Контейнер multiset (multiple-key set, мультимножество, множество с дубликатами) отличается от set лишь тем, что допускает включение одного и того же элемента по нескольку раз, например: {10, 20, 10, 30, 20}. В контейнере map (словарь) хранятся уникальные элементы – пары «ключзначение» , следующие в определенном порядке, устанавливаемом по значению ключа. Ключи элементов в контейнере map не могут быть изменены, но значения элементов могут быть изменены. Контейнер multimap (multiple-key map, словарь с дубликатами) отличается от map лишь тем, что допускает не уникальные ключи. Лекция 17 -21. 04. 2014 г. 5
Простой пример – частотный анализ слов в тексте #include <iostream> #include <string> #include <map> #include <fstream> using namespace std; int main() { map <string, int> words; ifstream in("in. txt"); string word; while(in >> word) words[word]++; ofstream out("out. txt"); for(auto cur : words) out << cur. first << ": " << cur. second << endl; return 0; } Лекция 17 -21. 04. 2014 г. 6
Создание (конструирование) ассоциативных контейнеров Каждый из шаблонных классов – set, multiset, map и multimap содержит конструкторы следующих видов: 1. Конструктор по умолчанию, который создает пустой контейнер. 2. Конструктор диапазона значений (range constructor) - создает контейнер, заполненный элементами из некоторой заданной последовательности. 3. Конструктор копирования. 4. Конструктор перемещения (move constructor). 5. Конструктор со списком инициализации. Лекция 17 -21. 04. 2014 г. 7
Создание set #include <set> #include <iostream> using namespace std; template <class T> void Print(string s, T q) { cout << s; for(auto& i : q) cout << " " << i; cout << endl; } int main( ) { set<int> first; // пустое множество Print("first = ", first); int myints[]= {10, 20, 30, 40, 50}; set<int> second (myints, myints+5); // диапазон значений Print("second = ", second); set<int> third (second); // копия существующего множества Print("third = ", third); auto i = second. begin(), j = second. end(); set<int> fourth (++i, --j); // диапазон с итератором Print("fourth = ", fourth); return 0; } Лекция 17 -21. 04. 2014 г. set 8
Создание set (с использованием объектов compare) #include <set> #include <iostream> using namespace std; // сравнивающий объект реализован как функция: bool fncomp (int lhs, int rhs) {return lhs > rhs; } // сравнивающий объект реализован как функтор: struct classcomp { bool operator() (const int& lhs, const int& rhs) const {return lhs > rhs; } }; template <class T> void Print(string s, T q) { cout << s; for(auto& i : q) cout << " " << i; cout << endl; } int main( ) { int myints[]= {10, 20, 30, 40, 50}; set<int, classcomp> fifth (myints, myints+5); // диапазон со сравн. объектом Print("fifth = ", fifth); set<int, bool(*)(int, int)> sixth (fncomp); // пустое мн-во со сравн. объектом for (auto i : myints) sixth. insert(i); Print("sixth = ", sixth); set<int, bool(*)(int, int)> seventh ({30, 45, 10, 55, 20}, fncomp); // Print("seventh = ", seventh); return 0; } set Лекция 17 -21. 04. 2014 г. 9
Создание multiset #include <set> #include <iostream> using namespace std; template <class T> void Print(string s, T q) { cout << s; for(auto& i : q) cout << " " << i; cout << endl; } int main( ) { multiset<int> first; // пустое множество Print("first = ", first); int myints[]= {10, 20, 30, 20}; multiset<int> second (myints, myints+5); // диапазон значений Print("second = ", second); multiset<int> third (second); // копия существующего множества Print("third = ", third); auto i = second. begin(), j = second. end(); multiset<int> fourth (++i, --j); // диапазон с итератором Print("fourth = ", fourth); return 0; } multiset Лекция 17 -21. 04. 2014 г. 10
Создание multiset (с использованием объектов compare) #include <set> #include <iostream> using namespace std; // сравнивающий объект реализован как функция: bool fncomp (int lhs, int rhs) {return lhs > rhs; } // сравнивающий объект реализован как функтор: struct classcomp { bool operator() (const int& lhs, const int& rhs) const {return lhs > rhs; } }; template <class T> void Print(string s, T q) { cout << s; for(auto& i : q) cout << " " << i; cout << endl; } int main( ) { int myints[]= {10, 20, 30, 20}; multiset<int, classcomp> fifth (myints, myints+5); // диапаз. со сравн. объектом Print("fifth = ", fifth); multiset<int, bool(*)(int, int)> sixth (fncomp); //пустое мн-во со сравн. объек. for (auto i : myints) sixth. insert(i); Print("sixth = ", sixth); multiset<int, bool(*)(int, int)> seventh ({30, 45, 15, 30, 45, 20}, fncomp); // Print("seventh = ", seventh); return 0; } multiset Лекция 17 -21. 04. 2014 г. 11
Создание map #include <map> #include <iostream> using namespace std; template <class T> void Print(string s, T q) { cout << s; for(auto& i : q) cout << " " << i. first << ': ' << i. second ; cout << endl; } int main( ) { map<char, int> first; // пустой словарь first['a']=10; first['b']=30; first['c']=50; first['d']=70; Print("first = ", first); map<char, int> second (first. begin(), first. end()); //диапазон значений Print("second = ", second); map<char, int> third (second); // копия существующего словаря Print("third = ", third); auto i = second. begin(), j = second. end(); map<char, int> fourth (++i, --j); // диапазон с итераторами Print("fourth = ", fourth); return 0; } map Лекция 17 -21. 04. 2014 г. 12
Создание map (с использованием объектов compare) #include <map> #include <iostream> using namespace std; // сравнивающий объект реализован как функция: bool fncomp (int lhs, int rhs) {return lhs>rhs; } // сравнивающий объект реализован как функтор: struct classcomp { bool operator() (const int& lhs, const int& rhs) const {return lhs>rhs; } }; int main( ) { map<char, int> first; // пустой словарь first['a']=10; first['b']=30; first['c']=50; first['d']=70; auto i = first. begin(), j = first. end(); ++i, --j; map<char, int, classcomp> fifth (i, j); // диапаз. со сравн. объектом Print("fifth = ", fifth); map<char, int, bool(*)(int, int)> sixth (fncomp); //пустой слов. со сравн. объек. for (auto i : first) sixth. insert(i); Print("sixth = ", sixth); map<char, int, bool(*)(int, int)> seventh ({{'e', 30}, {'f', 45}, {'g', 15}}, fncomp); Print("seventh = ", seventh); return 0; } map Лекция 17 -21. 04. 2014 г. 13
Создание multimap #include <map> #include <iostream> using namespace std; template <class T> void Print(string s, T q) { cout << s; for(auto& i : q) cout << " " << i. first << ': ' << i. second ; cout << endl; } int main( ) { multimap<char, int> first; // пустой словарь first. insert(pair<char, int>('a', 10)); first. insert(pair<char, int>('a', 20)); first. insert(pair<char, int>('b', 30)); first. insert(pair<char, int>('c', 40)); Print("first = ", first); multimap<char, int> second (first. begin(), first. end()); // диапазон значений Print("second = ", second); multimap<char, int> third (second); // копия существующего словаря Print("third = ", third); auto i = second. begin(), j = second. end(); multimap<char, int> fourth (++i, --j); // диапазон с итераторами Print("fourth = ", fourth); return 0; } multimap Лекция 17 -21. 04. 2014 г. 14
Создание multimap (с использованием объектов compare) #include <map> #include <iostream> using namespace std; // предикат реализован как функция: bool fncomp (int lhs, int rhs) {return lhs>rhs; } // предикат реализован как функтор: struct classcomp { bool operator() (const int& lhs, const int& rhs) const {return lhs>rhs; } }; int main( ) { multimap<char, int> first; // пустой словарь first. insert(pair<char, int>('a', 10)); first. insert(pair<char, int>('a', 20)); first. insert(pair<char, int>('b', 30)); first. insert(pair<char, int>('c', 40)); auto i = first. begin(), j = first. end(); ++i, --j; multimap<char, int, classcomp> fifth(i, j); // диапаз. со сравн. объектом Print("fifth = ", fifth); multimap<char, int, bool(*)(int, int)> sixth(fncomp); //пуст. слов. со сравн. объек. for (auto i : first) sixth. insert(i); Print("sixth = ", sixth); multimap<char, int, bool(*)(int, int)> seventh({{'e', 30}, {'f', 45}, {'f', 15}}, fncomp); Print("seventh = ", seventh); return 0; } Лекция 17 -21. 04. 2014 г. 15 multimap
Операция присваивания для ассоциативных контейнеров Операция присваивания для этих контейнеров имеет 3 перегрузки: #include <set> #include <iostream> using namespace std; template <class T> void Print(string s, T q) { cout << s; for(auto& i : q) cout << " " << i; cout << endl; } int main( ) { set<int> first({1, 2, 3, 4, 5, 6, 7}), second; Print("first = ", first); second = first; Print("second = ", second); // 1 set<double> third({1. 2, 0. 05, 4. 5, 0. 05, 1. 2}), fourth; Print("third = ", third); fourth = move(third); // 2 Print("fourth = ", fourth); Print("third = ", third); set<string> fifth; Print("fifth = ", fifth); fifth = {"Valencia", "Anita", "Sofia", "Agata", "Sara"}; // 3 Print("fifth = ", fifth); return 0; } Лекция 17 -21. 04. 2014 г. 16
Операция присваивания для ассоциативных контейнеров Пример со словарем : #include <map> #include <iostream> using namespace std; template <class T> void Print(string s, T q) { cout << s; for(auto& i : q) cout << " " << i. first << ': ' << i. second ; cout << endl; } int main( ) { map<char, int> first({{'f', 1}, {'s', 2}, {'b', 3}}), second; Print("first = ", first); second = first; Print("second = ", second); map<double, char> third({{1. 2, 'x'}, {0. 05, 'y'}, {4. 5, 'z'}}), fourth; Print("third = ", third); fourth = move(third); Print("fourth = ", fourth); Print("third = ", third); map<string, int> fifth; fifth = {{"Valencia", 15}, {"Anita", 19}, {"Sofia", 16}, {"Agata", 18}}; Print("fifth = ", fifth); return 0; } Лекция 17 -21. 04. 2014 г. 17
Функции, связанные с размером контейнера function set multiset map multimap max_size + + + + empty + + Лекция 17 -21. 04. 2014 г. 18
Итераторы function set multiset map multimap begin + + cbegin + + rbegin + + crbegin + + end + + cend + + rend + + crend + + Лекция 17 -21. 04. 2014 г. 19
Доступ к элементам function set multiset map multimap operator[] - - + - at - - + - operator[] – возвращает ссылку на значение элемента с заданным ключом. Если элемент с заданным ключом отсутствует в контейнере, то создается новый элемент (т. е. контейнер расширяется) at – возвращает ссылку на значение элемента с заданным ключом. Если элемент с заданным ключом отсутствует в контейнере, генерируется исключение Лекция 17 -21. 04. 2014 г. 20
Модификация контейнера function set multiset map multimap insert + + erase + + swap + + clear + + + + emplace_hint + + insert – расширяет контейнер путем вставки в него новых элементов (одного или нескольких) – 4 перегрузки erase – удаляет элементы из контейнера – 3 перегрузки swap – производит обмен содержимым между двумя контейнерами clear – удаляет все элементы из контейнера (очистка) emplace – конструирует новый элемент и вставляет его в контейнер emplace_hint – конструирует новый элемент и вставляет его в контейнер с «подсказкой» относительно места вставки Лекция 17 -21. 04. 2014 г. 21
Операция вставки #include <set> #include <iostream> using namespace std; template <class T> void Print(string s, T q) { cout << s; for(auto& i : q) cout << " " << i; cout << endl; } int main () { set<int> myset; auto it = myset. begin(); for (int i=1; i<=5; ++i) myset. insert(i*10); Print("myset = ", myset); auto ret = myset. insert(20); // элемент 20 не будет вставлен Print("myset = ", myset); if (ret. second==false) it=ret. first; // "it" указывает на 20 myset. insert (it, 25); // вставка с «подсказкой» myset. insert (it, 24); // вставка с «подсказкой» myset. insert (it, 26); // вставка с «подсказкой» Print("myset = ", myset); int myints[]= {5, 10, 15}; // элемент 10 не будет вставлен myset. insert (myints, myints+3); Print("myset = ", myset); myset. insert ({44, 33, 22, 11}); Print("myset = ", myset); return 0; } Лекция 17 -21. 04. 2014 г. 22
Операции удаления и обмена #include <set> #include <iostream> using namespace std; template <class T> void Print(string s, T q) { cout << s; for(auto& i : q) cout << " " << i; cout << endl; } int main () { set<int> myset, myset 1; for (int i=1; i< 10; ++i) myset. insert(i*10); auto it = myset. begin(); Print("myset = ", myset); myset 1 = myset; myset. erase(++it); Print("myset = ", myset); myset. erase (40); Print("myset = ", myset); it = myset. find (60); myset. erase (it, myset. end()); Print("myset = ", myset); myset. swap(myset 1); Print("myset = ", myset); Print("myset 1 = ", myset 1); myset. clear(); Print("myset = ", myset); return 0; } Лекция 17 -21. 04. 2014 г. 23
Сравнивающие объекты function set multiset map multimap key_comp + + value_comp + + key_comp – возвращает копию сравнивающего объекта (comparison object), который используются для сравнения ключей контейнера value_comp – возвращает копию сравнивающего объекта (comparison object), который используются для сравнения элементов контейнера по ключу (т. е. value_comp работает непосредственно с элементами, а не с ключами, как key_comp) Лекция 17 -21. 04. 2014 г. 24
Прочие операции function set multiset map multimap find + + count + + lower_bound + + upper_bound + + equal_range + + find – возвращает итератор на элемент с заданным ключом, или end(), если такой элемент отсутствует count – возвращает количество элементов с заданным ключом, или 0, если такие элементы отсутствуют lower_bound - возвращает итератор на первый по порядку элемент , начиная с которого все элементы имеют ключи, большие или равные заданному ключу upper_bound - возвращает итератор на элемент , начиная с которого все элементы имеют ключи, большие заданного ключа equal_range - возвращает границы диапазона (пару итераторов), который включает в себя все элементы в контейнере, ключи которых равны заданному ключу Лекция 17 -21. 04. 2014 г. 25
Операция для работы с границами (диапазонами) #include <set> #include <iostream> using namespace std; template <class T> void Print(string s, T q) { cout << s; for(auto& i : q) cout << " " << i; cout << endl; } int main( ) { multiset<int> ms({10, 20, 30, 20, 40, 50, 30, 50}); Print("ms = ", ms); auto i = ms. lower_bound(20), j = ms. upper_bound(40); multiset<int> ms 1(i, j); Print("ms 1 = ", ms 1); auto p = ms. equal_range(30); multiset<int> ms 2(p. first, p. second); Print("ms 2 = ", ms 2); return 0; } Лекция 17 -21. 04. 2014 г. 26
Лекция-2.09.ppt