Итераторы и алгоритмы — различия между версиями
Строка 66: | Строка 66: | ||
Каждый алгоритм может работать только с определенными типами итераторов. Необходимый тип будет указываться в качестве типа аргумента. | Каждый алгоритм может работать только с определенными типами итераторов. Необходимый тип будет указываться в качестве типа аргумента. | ||
− | Например, запись <tt>count(Input p, Input q, T value)</tt> означает, что функция <tt>count</tt> принимает на вход итератор типа Input. | + | Например, запись <tt>count(Input p, Input q, T value)</tt> означает, что функция <tt>count</tt> принимает на вход итератор типа <tt>Input</tt>. |
Под записью "итератор на элемент" следует понимать "итератор, указывающий на элемент". | Под записью "итератор на элемент" следует понимать "итератор, указывающий на элемент". | ||
Строка 74: | Строка 74: | ||
<tt>swap(T& a, T& b)</tt> меняет местами значения объектов. | <tt>swap(T& a, T& b)</tt> меняет местами значения объектов. | ||
− | <tt>iter_swap(Forward1 a, Forward2 b)</tt> меняет местами значения, на которые указывают итераторы (равносилен swap(*a, *b)). | + | <tt>iter_swap(Forward1 a, Forward2 b)</tt> меняет местами значения, на которые указывают итераторы (равносилен <tt>swap(*a, *b)</tt>). |
<tt>min(const T& a, const T&b [, Compare cmp ])</tt> находит минимум двух элементов и возвращает ссылку на минимальный. Может на вход принимать третий аргумент: компоратор, т.е. функций, которой надо сравнивать элементы. | <tt>min(const T& a, const T&b [, Compare cmp ])</tt> находит минимум двух элементов и возвращает ссылку на минимальный. Может на вход принимать третий аргумент: компоратор, т.е. функций, которой надо сравнивать элементы. | ||
Строка 80: | Строка 80: | ||
<tt>max(const T& a, const T&b [, Compare cmp ])</tt> аналогичен минимуму. | <tt>max(const T& a, const T&b [, Compare cmp ])</tt> аналогичен минимуму. | ||
− | ''Замечание'' В хедере win.h есть дефайны min и max. Если нужны функции из STL-а, стоит отключить min и max через undef. | + | ''Замечание'' В хедере win.h есть дефайны min и max. Если нужны функции из STL-а, стоит отключить <tt>min</tt> и <tt>max</tt> через <tt>undef</tt>. |
=== Не модифицирующие алгоритмы === | === Не модифицирующие алгоритмы === | ||
− | <tt>count(Input p, Input q, T value)</tt> находит число вхождений элемента value в коллекцию [p, q). | + | <tt>count(Input p, Input q, T value)</tt> находит число вхождений элемента <tt>value</tt> в коллекцию <tt>[p, q)</tt>. |
− | <tt>count_if(Input p, Input q, UPredicate pr)</tt> находит число элементов коллекции [p, q), удовлетворяющий унарному предикату pr. | + | <tt>count_if(Input p, Input q, UPredicate pr)</tt> находит число элементов коллекции <tt>[p, q)</tt>, удовлетворяющий унарному предикату <tt>pr</tt>. |
− | <tt>for_each(Input p, Input q, Func f)</tt> вызывает последовательно функцию f для каждого элемента коллекции [p, q). | + | <tt>for_each(Input p, Input q, Func f)</tt> вызывает последовательно функцию <tt>f</tt> для каждого элемента коллекции <tt>[p, q)</tt>. |
− | <tt>equal(Input p1, Input q1, Input p2 [, BPredicate pr])</tt> сравнивает две последовательности [p1, q1), [p2, ?). Возвращает true, если первая является префиксом второй, т.е. элементы из [p1, q1) совпадают с первыми q1 - p1 элементами [p2, ?). В качестве дополнительного аргумента можно передать бинарный предикат равенства. Если вторая последовательность оказывается короче первой, поведение функции не определено | + | <tt>equal(Input p1, Input q1, Input p2 [, BPredicate pr])</tt> сравнивает две последовательности <tt>[p1, q1)</tt>, <tt>[p2, ?)</tt>. Возвращает <tt>true</tt>, если первая является префиксом второй, т.е. элементы из <tt>[p1, q1)</tt> совпадают с первыми <tt>q1 - p1</tt> элементами <tt>[p2, ?)</tt>. В качестве дополнительного аргумента можно передать бинарный предикат равенства. Если вторая последовательность оказывается короче первой, поведение функции не определено. |
− | <tt>mismatch(Input p1, Input q1, Input p2[, BPredicate pr])</tt> сравнивает две последовательности [p1, q1), [p2, ?). Возвращает пару итераторов, указывающих на первое различие. Если [p1, q1) является префиксом [p2, ?), то mismatch возвращает пару (q1, q2), где q2 является элементов соответствующим q1 в [p2, ?). | + | <tt>mismatch(Input p1, Input q1, Input p2[, BPredicate pr])</tt> сравнивает две последовательности <tt>[p1, q1)</tt>, <tt>[p2, ?)</tt>. Возвращает пару итераторов, указывающих на первое различие. Если <tt>[p1, q1)</tt> является префиксом <tt>[p2, ?)</tt>, то <tt>mismatch</tt> возвращает пару <tt>(q1, q2)</tt>, где <tt>q2</tt> является элементов соответствующим <tt>q1</tt> в <tt>[p2, ?)</tt>. |
− | <tt>lexicographical_compare(Input p1, Input q1, Input p2, Input q2[, Compare cmp])</tt> возвращает меньше ли лексикографически [p1, q1) чем [p2, q2). Имеет дополнительный аргумент: компаратор cmp, сравнивающий два элемента последовательностей. | + | <tt>lexicographical_compare(Input p1, Input q1, Input p2, Input q2[, Compare cmp])</tt> возвращает меньше ли лексикографически <tt>[p1, q1)</tt> чем <tt>[p2, q2)</tt>. Имеет дополнительный аргумент: компаратор cmp, сравнивающий два элемента последовательностей. |
− | <tt>min_element(Forward p1, Forward q1[, Compare cmp])</tt> возвращает итератор, указывающий на минимальный элемент в последовательности [p1, q1). Имеет дополнительный аргумент: компаратор cmp. | + | <tt>min_element(Forward p1, Forward q1[, Compare cmp])</tt> возвращает итератор, указывающий на минимальный элемент в последовательности <tt>[p1, q1)</tt>. Имеет дополнительный аргумент: компаратор <tt>cmp</tt>. |
− | <tt>max_element(Forward p1, Forward q1[, Compare cmp])</tt> аналогичен min_element. | + | <tt>max_element(Forward p1, Forward q1[, Compare cmp])</tt> аналогичен <tt>min_element</tt>. |
− | <tt>search(Forward1 p1, Forward q1, Forward p2, Forward q2[, BPredicate pred])</tt> находит первое вхождение последовательности [p2, q2) | + | <tt>search(Forward1 p1, Forward q1, Forward p2, Forward q2[, BPredicate pred])</tt> находит первое вхождение последовательности <tt>[p2, q2)</tt> |
Версия 23:37, 14 мая 2011
Содержание
Итераторы
Итератор --- это объект, указывающий на некоторый элемент цепочки элементов, позволяющий перебирать элементы цепочки с помощью некоторого набора операций. Процесс перебора элементов цепочки называется итерированием.
Наиболее очевидный пример итератора --- это указатель: указывает на объект, позволяет итерировать массив через инкремент и декремент. В C++ синтаксис итераторов заимствован у указателей.
Классификация
Выделяют пять типов итераторов. Ниже представлены итераторы в порядке убывания их силы.
- Random Access. Это наиболее мощный тип итераторов. Random access поддерживает произвольный доступ к последовательности элементов. По сути равносилен указателем: поддерживает операции инкремента(++), декремента (--), прибавления целого числа (+ val, - val), разыменования (*), разыменования со сдвигом ([]), доступа к члену (->). Как пример, итераторы такого типа предоставляет vector.
- Bidirectional. Двунаправленный итератор является более слабым типом итераторов: позволяет двигаться только вперед и назад, проходя через каждый элемент. Операции: ++, --, *, ->. Как пример, итераторы такого типа предоставляет list.
- Forward. Однонаправленный итератор позволяет двигаться только в одном направлении. Операции: ++, *, ->
- Input. Однонаправленный итератор, позволяющий только считывать данные, но не записывать.
- Output. Однонаправленный итератор, позволяющий только записывать данные, но не считывать.
Вне данной классификации лежит Reverse iterator. Reverse iterator обращает направление для bidirectional и random access итераторов. Для получения начала и конца итератора необходимо вызвать rbegin() и rend() соответственно. Reverse iterator реализует функцию base(), возвращающую обычный итератор. Для того, чтобы получить из обычного (bidirectional и random access) итератора reverse, достаточно использовать оператор присваивания.
set< int > s;
set< int > :: reverse_iterator i = s.rbegin();
set< int > :: iterator j = i.base();
i = j
Внимание, вопрос. Почему в одну сторону можно написать i = j, а в другую только j = i.base()?
Внимание, вопрос. Почему нельзя менять значения в set?
Служебная информация
Для описания итератора в С++ существует шаблон iterator_traits. Стандартные алгоритмы получают необходимую информацию об итераторах из специализаций этого шаблона для конкретного итератора.
Определение iterator_traits выглядит следующим образом.
template <class Iterator> struct iterator_traits {
typedef typename Iterator::difference_type difference_type;
typedef typename Iterator::value_type value_type;
typedef typename Iterator::pointer pointer;
typedef typename Iterator::reference reference;
typedef typename Iterator::iterator_category iterator_category;
}
- difference_type описывает тип разности итераторов.
- value_type --- тип объекта, на который указывает итератор.
- pointer --- тип указателя на объект
- reference --- тип ссылки
- iterator_category_tag --- категория итератора. Может быть
- input_iterator_tag
- output_iterator_tag
- forward_iterator_tag
- bidirectional_iterator_tag
- random_access_iterator_tag
Стандартные функции
advance(iterator, n) --- сдвигает итератор на n элементов. Для random access и bidirectional значение n может быть отрицательным. Работает со всеми типами итераторов вплоть до input. Для random access сдвигается сразу на n элементов, для остальных --- использует инкремент (или декремент).
distance(iterator first, iterator last) находит число элементов между first и last. Для radnom access использует значение разности итераторов, для остальных --- использует линейный поиск.
Алгоритмы
C++ поддерживает набор функций, позволяющий работать с цепочками элементов (range of elements). Джентльменский набор таких функций объявлен в хедере <algorithm>.
Каждый алгоритм может работать только с определенными типами итераторов. Необходимый тип будет указываться в качестве типа аргумента. Например, запись count(Input p, Input q, T value) означает, что функция count принимает на вход итератор типа Input.
Под записью "итератор на элемент" следует понимать "итератор, указывающий на элемент".
Общие функции
swap(T& a, T& b) меняет местами значения объектов.
iter_swap(Forward1 a, Forward2 b) меняет местами значения, на которые указывают итераторы (равносилен swap(*a, *b)).
min(const T& a, const T&b [, Compare cmp ]) находит минимум двух элементов и возвращает ссылку на минимальный. Может на вход принимать третий аргумент: компоратор, т.е. функций, которой надо сравнивать элементы.
max(const T& a, const T&b [, Compare cmp ]) аналогичен минимуму.
Замечание В хедере win.h есть дефайны min и max. Если нужны функции из STL-а, стоит отключить min и max через undef.
Не модифицирующие алгоритмы
count(Input p, Input q, T value) находит число вхождений элемента value в коллекцию [p, q).
count_if(Input p, Input q, UPredicate pr) находит число элементов коллекции [p, q), удовлетворяющий унарному предикату pr.
for_each(Input p, Input q, Func f) вызывает последовательно функцию f для каждого элемента коллекции [p, q).
equal(Input p1, Input q1, Input p2 [, BPredicate pr]) сравнивает две последовательности [p1, q1), [p2, ?). Возвращает true, если первая является префиксом второй, т.е. элементы из [p1, q1) совпадают с первыми q1 - p1 элементами [p2, ?). В качестве дополнительного аргумента можно передать бинарный предикат равенства. Если вторая последовательность оказывается короче первой, поведение функции не определено.
mismatch(Input p1, Input q1, Input p2[, BPredicate pr]) сравнивает две последовательности [p1, q1), [p2, ?). Возвращает пару итераторов, указывающих на первое различие. Если [p1, q1) является префиксом [p2, ?), то mismatch возвращает пару (q1, q2), где q2 является элементов соответствующим q1 в [p2, ?).
lexicographical_compare(Input p1, Input q1, Input p2, Input q2[, Compare cmp]) возвращает меньше ли лексикографически [p1, q1) чем [p2, q2). Имеет дополнительный аргумент: компаратор cmp, сравнивающий два элемента последовательностей.
min_element(Forward p1, Forward q1[, Compare cmp]) возвращает итератор, указывающий на минимальный элемент в последовательности [p1, q1). Имеет дополнительный аргумент: компаратор cmp.
max_element(Forward p1, Forward q1[, Compare cmp]) аналогичен min_element.
search(Forward1 p1, Forward q1, Forward p2, Forward q2[, BPredicate pred]) находит первое вхождение последовательности [p2, q2)