Анимация
JavaScript


Главная  Библионтека 

0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 [ 30 ] 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239

Первые два алгоритма называются min element() и max element(). При вызов им передаются два параметра, определяющих интервал обрабатываемых элемен тов. Чтобы обработать все содержимое контейнера, просто используйте вызов! beginO и end(). Алгоритмы возвращают итераторы соответственно для минималь ного и максимального элементов. Таким образом, в показанной ниже команд алгоритм min element() возвращает позицию минимального элемента (если таки: элементов несколько, алгоритм возвращает позицию первого из них):

pos = [nin element (coll .beginC). coll.endO):

Следующая команда выводит найденный элемент: cout « "шШ: " « *pos « endl:

Разумеется, поиск и вывод можно объединить в одну команду:

cout « *[n1n element(coll .beginO.coll .endO.endO) « endl;

Следующим вызывается алгоритм sort(). Как нетрудно догадаться по названию, этот алгоритм сортирует элементы в интервале, определяемом двумя аргументами. Как обычно, вы можете задать собственный критерий сортировки. По умолчанию сортировка осуществляется с использованием оператора <. Таким образом, следующая команда сортирует все элементы контейнера по возрастанию:

sort (coll.beginO. coll.endO):

В конце концов элементы вектора будут расположены в следующем порядке:

1 2 3 4 5 6

Алгоритм find() ищет значение в заданном интервале. В нашем примере во всем контейнере ищется первый элемент со значением 3:

pos = find (coll.beginO. coll.endO. Интервал 3): Значение

Если поиск оказался успешным, алгоритм find() возвращает итератор, установленный на первый найденный элемент. В случае неудачи возвращается итератор} для позиции за концом интервала, определяемым вторым переданным аргументом. В нашем примере значение 3 находится в третьем элементе, поэтому pos ссылается на третий элемент coll.

Последним вызывается алгоритм reverse(), который переставляет элементы переданного интервала в обратном порядке. В аргументах передается третий элемент, найденный алгоритмом find(), и конечный итератор:

reverse (pos. coll.endO);

В результате вызова переставляются элементы от третьего до последнего. Результат работы программы выглядит так:

min: 1 max: 6 1 2 6 5 4 3



Интервалы

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

Такой интерфейс чрезвычайно гибок, но потенциально опасен. Вызывающая сторона должна проследить за тем, чтобы первый и второй аргументы определяли действительный интервал, то есть итератор мог перейти от начала к концу интервала в процессе перебора элементов. А это означает, что оба итератора должны принадлежать одному контейнеру, а начало интервала не должно находиться после его конца. Если это условие не выполняется, возможны непредсказуемые последствия, включая зацикливание или нарушение защиты памяти. В этом отношении итераторы так же ненадежны, как обычные указатели. Однако из неопределенности поведения также следует, что реализации STL могут выявлять подобные ошибки и обрабатывать их по своему усмотрению. Как вы вскоре убедитесь, проверить правильность интервала далеко не всегда так просто, как кажется на первый взгляд. За дополнительной информацией о потенциальных проблемах и безопасных версиях STL обращайтесь на с. 146.

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

[начало,конец) [начало.иоиеи1

В книге используется первый вариант.

Концепция полуоткрытых интервалов обладает рядом достоинств, упоминавшихся на с. 96 (эта концепция проста ц не требует специальной обработки пустых коллекций). Тем не менее у нее также есть недостатки. Рассмотрим следующий пример:

stl/findl.cpp #1nclude <iostream> #include <list> #include <algorithm> using namespace std:

int mainO {

l1St<int> coll ;

list<int>::iterator pos;

Вставка элементов от 20 до 40 for (int 1=20; 1<=40: ++i) { coll.pLJSh back(1);



Поиск позиции элемента со значением, равным 3

* - такой элемент отсутствует, поэтому pos присваивается coll.endO */

pos = find Cecil .beginC). coll.endO, Интервал

3); Значение

/* Перестановка злементов от найденного до конца интервала

* - поскольку итератор pos равен coll.endO.

* перестановка производится в пустом интервале. */

reverse (pos, coll.endO);

Поиск позиций со значениями 25 и 25

11st<int>;:iterator pos25, ро535;

pQs25 = find (coll.beginO, coll.endO. Интервал

25): Значение

pos35 = find (coll.beginO. coll.endO. Интервал

35); Значение

/* Вывод максимума ло полученному интервалу

* - обратите внимание: интервап содержит позицию pos25.

* но позиция pos35 в него не включается. */

cout « "max: " « *max element (pos25. pos35) « endl:

process the elements including the last position cout « "max: " « *max element (po525. ++pos35) « endl;

В этом примере коллекция заполняется целыми числами от 20 до 40. После того как поиск элемента со значением 3 завершается неудачей, find() возвращает конец обработанного интервала - в данном случае coll.endO ~ и присваивает его переменной pos. Использование возвращаемого значения в качестве начала интервала при вызове reverse() не вызывает проблем, поскольку это приводит к следующему вызову:

reverse (coll.endO. coll.endO);

Происходит перестановка элементов в пустом интервале, поэтому никакие реальные действия не выполняются.

Но если алгоритм find() используется для определения первого и последнего элементов в подмножестве, следует помнить, что при определении интервала на основании полученных итераторов последний элемент исключается. Рассмотрим первый вызов max element():

max element (pos25. pos35)

При этом вызове будет найдено максимальное значение 34 вместо 35:

max; 34



0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 [ 30 ] 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239