c++ 2, весна 2015: stl: ассоциативные контейнеры и итераторы

23
STL: ассоциативные контейнеры и итераторы STL: ассоциативные контейнеры и итераторы Александр Смаль CS центр 19 февраля 2014 Санкт-Петербург http://compscicenter.ru 1/23

Upload: cs-center

Post on 09-Aug-2015

296 views

Category:

Documents


0 download

TRANSCRIPT

Page 1: C++ 2, весна 2015: STL: ассоциативные контейнеры и итераторы

STL: ассоциативные контейнеры и итераторы

STL: ассоциативные контейнеры иитераторы

Александр Смаль

CS центр19 февраля 2014Санкт-Петербург

http://compscicenter.ru 1/23

Page 2: C++ 2, весна 2015: STL: ассоциативные контейнеры и итераторы

STL: ассоциативные контейнеры и итераторы

STL: введение∙ STL = Standard Template Library∙ STL описан в стандарте C++, но не упоминается там явно.∙ Авторы: Александр Степанов, Дэвид Муссер и Менг Ли

для HP, а потом для SGI.∙ Основан на разработках для языка Ада.∙ Основные составляющие:

∙ контейнеры (хранение объектов в памяти),∙ итераторы (доступ к элементам контейнера),∙ алгоритм (для работы с последовательностями),∙ адаптеры (обёртки над контейнерами)∙ функциональные объекты, функторы (обобщение

функций).∙ потоки ввода/вывода.

∙ Всё определено в пространстве имён std.http://compscicenter.ru 2/23

Page 3: C++ 2, весна 2015: STL: ассоциативные контейнеры и итераторы

STL: ассоциативные контейнеры и итераторы

Общие сведения о контейнерахКонтейнеры библиотеки STL можно разделить на четырекатегории:

∙ последовательные,∙ ассоциативные,∙ контейнеры-адаптеры,∙ псевдоконтейнеры.

Требования к хранимым объектам:1. copy-constuctable2. assignable3. “стандартная семантика”

Итераторы — объекты для доступа к элементам контейнера ссинтаксисом указателей.

http://compscicenter.ru 3/23

Page 4: C++ 2, весна 2015: STL: ассоциативные контейнеры и итераторы

STL: ассоциативные контейнеры и итераторы

Общие члены контейнеровТипы (typedef-ы или вложенные класс):

1. C::value_type2. C::reference3. C::const_reference4. C::pointer5. C::iterator6. C::const_iterator7. C::size_type

Методы:1. Конструктор по умолчанию, конструктор копирования,

оператор присваивания, деструктор.2. begin(), end()3. Операторы сравнения: ==, !=, >, >=, <, <=.4. size(), empty().5. swap(obj2)6. clear.

http://compscicenter.ru 4/23

Page 5: C++ 2, весна 2015: STL: ассоциативные контейнеры и итераторы

STL: ассоциативные контейнеры и итераторы

Ассоциативные контейнеры

Общие методы:1. erase по key2. count

3. find

4. lower_bound, upper_bound, equal_range

5. insert с подсказкойОсобенности:

1. Требуют отношение порядка.2. Нет произвольного доступа.

http://compscicenter.ru 5/23

Page 6: C++ 2, весна 2015: STL: ассоциативные контейнеры и итераторы

STL: ассоциативные контейнеры и итераторы

set, multisetstd::set <int > primes;

primes.insert (2);

primes.insert (3);

primes.insert (5);

...

if (primes.find (173) != primes.end ())

std::cout << 173 << " is prime\n";

for(std::set <int >:: iterator it = primes.begin ();

it != primes.end(); ++it)

std::cout << *it << ’\n’;

// –––––––––––––––-

std::multiset <int > ms;

ms.insert (1);

ms.insert (2);

ms.insert (2); // ms.size() == 3

std::cout << ms.count (2) << ’\n’;

http://compscicenter.ru 6/23

Page 7: C++ 2, весна 2015: STL: ассоциативные контейнеры и итераторы

STL: ассоциативные контейнеры и итераторы

map, multimapХранит пару ключ-значение std::pair.template <class F, class S>

struct pair {

... // constructors

F first;

S second;

};

template <class F, class S>

pair <F, S> make_pair(F const& f, S const& s);

template <class Key , class T, ...> class map {

...

typedef pair <const Key , T> value_type;

} ;

Особые методы:∙ operator[]

http://compscicenter.ru 7/23

Page 8: C++ 2, весна 2015: STL: ассоциативные контейнеры и итераторы

STL: ассоциативные контейнеры и итераторы

map, multimapstd::map <string ,int > phonebook;

phonebook.insert(std:: make_pair("Mary", 2128506));

phonebook.insert(std:: make_pair("Alex", 9286385));

phonebook.insert(std:: make_pair("Bob", 2128506));

...

std::map <string ,int >:: iterator it = phonebook.find("John");

if ( it != phonebook.end())

std::cout << "Jonh’s p/n is " << it->second << "\n";

for(it = phonebook.begin (); it != phonebook.end(); ++it)

std::cout << it->first << ": " << it->second << "\n";

// –––––––––––––––-

std::multmap <string , int > pb;

pb.insert(std:: make_pair("Mary", 2128506));

pb.insert(std:: make_pair("Mary", 2128507));

pb.insert(std:: make_pair("Mary", 1112223)); //ms.size()==3

std::cout << pb.count("Mary") << ’\n’;

http://compscicenter.ru 8/23

Page 9: C++ 2, весна 2015: STL: ассоциативные контейнеры и итераторы

STL: ассоциативные контейнеры и итераторы

map::operator[]std::map <string , int > phonebook;

phonebook.insert(std:: make_pair("Mary", 2128506));

...

phonebook.insert(std:: make_pair("Mary", 2128507)); // fail

std::pair <std::map <string , int >:: iterator , bool > res =

phonebook.insert("Mary", 2128507); // res.second == false

std::map <string , int >:: iterator it = phonebook.find("Mary");

if (it != phonebook.end() )

it->second = 2128507;

else phonebook.insert(std:: make_pair("Mary", 2128507));

// OR

phonebook["Mary"] = 2128507;

for(it = phonebook.begin (); it != phonebook.end(); ++it)

std::cout << it->first << ": " << phonebook[it ->first] << "\n";

http://compscicenter.ru 9/23

Page 10: C++ 2, весна 2015: STL: ассоциативные контейнеры и итераторы

STL: ассоциативные контейнеры и итераторы

Ограничения map::operator[]

1. Работает только с неконстантным map.2. Требует наличие конструктора по умолчанию у T.

T & operator []( Key const& k)

{

iterator i = find(k);

if (i == end())

i = insert(value_type(k, T())). first;

return i->second;

}

3. Работает за O(log n). ⇒ Не стоит работать с map как cмассивом!

http://compscicenter.ru 10/23

Page 11: C++ 2, весна 2015: STL: ассоциативные контейнеры и итераторы

STL: ассоциативные контейнеры и итераторы

Удаление из set и mapНеправильный вариантstd::map <string , int > m;

std::map <string , int >:: iterator it = m.begin ();

for( ; it != m.end(); ++it)

if (it->second == 0)

m.erase(it);

Непереносимый вариант (стандарт C++ 11)for( ; it != m.end(); )

if (it->second == 0) it = m.erase(it);

else ++it;

Правильный вариантfor( ; it != m.end(); )

if (it->second == 0) m.erase(it++);

else ++it;

http://compscicenter.ru 11/23

Page 12: C++ 2, весна 2015: STL: ассоциативные контейнеры и итераторы

STL: ассоциативные контейнеры и итераторы

Использование собственного компаратораstruct Person {

string name;

string surname;

};

bool operator <( Person const& a, Person const& b) {

return a.name < b.name ||

(a.name == b.name && a.surname < b.surname );

}

std::set <Person > s1; // unique by name+surname

struct PersonComp {

bool operator ()( Person const& a, Person const& b) const {

return a.surname < b.surname;

}

};

std::set <Person , PersonComp > s2; // unique by surnames

http://compscicenter.ru 12/23

Page 13: C++ 2, весна 2015: STL: ассоциативные контейнеры и итераторы

STL: ассоциативные контейнеры и итераторы

Требования к компаратору

Компаратор должен задавать отношение строгого порядка:¬(x ≺ y) ∧ ¬(y ≺ x) ⇒ x = y

http://compscicenter.ru 13/23

Page 14: C++ 2, весна 2015: STL: ассоциативные контейнеры и итераторы

STL: ассоциативные контейнеры и итераторы

insert с подсказкой

std::map <K, V> m;

K k = ...;

V v = ...;

std::map <K, V>:: iterator i = m.find(k); // returns m.end()

std::map <K, V>:: iterator hint = m.lower_bound(k);

if (hint != m.end() && !(k < hint ->first ))

// gotcha!

else

// use hint

m.insert(hint , std:: make_pair(k, v));

http://compscicenter.ru 14/23

Page 15: C++ 2, весна 2015: STL: ассоциативные контейнеры и итераторы

STL: ассоциативные контейнеры и итераторы

Категории итераторовИтератор — синтаксически похожий на указатель объект длядоступа к элементам последовательности.Итераторы делятся на пять категорий.

∙ Random access iterator. ++, --, арифметика, read-write∙ Bidirectional iterator. ++, --, read-write∙ Forward iterator. ++, read-write∙ Input iterator. ++, read∙ Output iterator. ++, write

Функции для работы с итераторами:

void advance (Iterator & it, size_t n);

size_t distance (Iterator f, Iterator l);

void iter_swap(Iterator i, Iterator j);

http://compscicenter.ru 15/23

Page 16: C++ 2, весна 2015: STL: ассоциативные контейнеры и итераторы

STL: ассоциативные контейнеры и итераторы

iterator_traits// <iterator>

template <class Iterator >

struct iterator_traits {

typedef difference_type Iterator :: difference_type;

typedef value_type Iterator :: value_type;

typedef pointer Iterator :: pointer;

typedef reference Iterator :: reference;

typedef iterator_category Iterator :: iterator_category;

};

template <class Iterator >

void iter_swap(Iterator i, Iterator j) {

// Iterator::value_type t = *i;

typename iterator_traits <Iterator >:: value_type t = *i;

*i = *j;

*j = t;

}

http://compscicenter.ru 16/23

Page 17: C++ 2, весна 2015: STL: ассоциативные контейнеры и итераторы

STL: ассоциативные контейнеры и итераторы

iterator_traits для указателей

// <iterator>

template <class T>

struct iterator_traits <T *> {

typedef difference_type ptrdiff_t;

typedef value_type T;

typedef pointer T*;

typedef reference T&;

typedef iterator_category random_access_iterator_tag;

};

http://compscicenter.ru 17/23

Page 18: C++ 2, весна 2015: STL: ассоциативные контейнеры и итераторы

STL: ассоциативные контейнеры и итераторы

iterator_categorystruct bidirectional_iterator_tag {};

struct forward_iterator_tag {};

struct input_iterator_tag {};

struct output_iterator_tag {};

struct random_access_iterator_tag {};

template <class Iterator >

void advance(Iterator & i, size_t n) {

advance_impl(i, n, typename iterator_traits <Iterator >::

iterator_category ());

}

template <class Iterator >

void advance_impl(Iterator & i, size_t n, random_access_iterator_tag)

{ i += n; }

template <class Iterator >

void advance_impl(Iterator & i, size_t n, ... ) {

for (size_t k = 0; k != n; ++k, ++i );

} http://compscicenter.ru 18/23

Page 19: C++ 2, весна 2015: STL: ассоциативные контейнеры и итераторы

STL: ассоциативные контейнеры и итераторы

reverse_iteratorУ стандартных контейнеров есть обратные итераторы:

list <int > l;

for(list <int >:: reverse_iterator i = l.rbegin ();

i != l.rend (); ++i)

...

Конвертация итераторов:iterator i;

reverse_iterator ri = i;

i = ri.base ();

Есть возможность сделать reverse итератор по RA или BiDi.#include <iterator >

template <class Iterator >

class reverse_iterator;

http://compscicenter.ru 19/23

Page 20: C++ 2, весна 2015: STL: ассоциативные контейнеры и итераторы

STL: ассоциативные контейнеры и итераторы

Advanced итераторыОпределены следующие специальные итераторы итераторов:

1. back_inserter, front_inserter, inserter2. istream_iterator, ostream_iterator

vector <Person > db;

template <class OutIt >

void findByName(vector <Person > const& db ,

string name , OutIt out);

...

vector <Person > res; // size is not known

findByName(db , "Ivan", std:: back_inserter(res ));

ifstream file("input.txt");

vector <double > v(( istream_iterator <double >(file)),

istream_iterator <double >());

copy(v.begin(), v.end(), ostream_iterator <double >(cout , ’\n’));

http://compscicenter.ru 20/23

Page 21: C++ 2, весна 2015: STL: ассоциативные контейнеры и итераторы

STL: ассоциативные контейнеры и итераторы

Как написать свой итератор

#include <iterator >

template

<class Category , // iterator::iterator_category

class T, // iterator::value_type

class Distance = ptrdiff_t ,// iterator::difference_type

class Pointer = T*, // iterator::pointer

class Reference = T& // iterator::reference

> class iterator;

struct MyIterator

: std::iterator <bidirectional_iterator_tag , Person >

{

// ++, --, ...

};

http://compscicenter.ru 21/23

Page 22: C++ 2, весна 2015: STL: ассоциативные контейнеры и итераторы

STL: ассоциативные контейнеры и итераторы

Функторы и предикаты∙ Функтор — класс, объекты которого ведут себя как

функции, т.е. имеет перегруженные operator()∙ Предикат — функтор возвращающий bool.

Функторы в стандартной библиотеке:1. less, greater, less_equal, greater_equal,

not_equal_to, equal_to2. minus, plus, divides, modulus, multiplies3. logical_not, logical_and, logical_or4. mem_fun, mem_fun_ref, ptr_fun5. bind1st, bind2nd, not1, not2

map <int , string , greater <int >> m;

bind2nd(less <int >(), 10);

bind1st(modulus <size_t >, 1024);

not1(logical_not <bool >());http://compscicenter.ru 22/23

Page 23: C++ 2, весна 2015: STL: ассоциативные контейнеры и итераторы

STL: ассоциативные контейнеры и итераторы

Как написать свой функтор#include <functional >

template <class Arg , class Result >

struct unary_function {

typedef Arg argument_type;

typedef Result result_type;

};

template <class Arg1 , class Arg2 , class Result >

struct binary_function {

typedef Arg1 first_argument_type;

typedef Arg2 second_argument_type;

typedef Result result_type;

};

struct MyFunctor : binary_function <int , double , size_t >

{

size_t operator ()(int i, double d) {...}

};

http://compscicenter.ru 23/23