5. Вставьте новое значение в контейнер. Если новый элемент в порадке сортировки контейнера находится в позиции удаленного элемента или в соседней позиции, воспользуйтесь «рекомендательной» формой insert
, повышающей эффективность вставки от логарифмической до постоянной сложности. В качестве рекомендации обычно используется итератор, полученный на шаге 1.
EmpIDSet se; // Контейнер set объектов Employee, упорядоченных по коду
Employee SelectedID; // Объект работника с заданным кодом
…
EmpIDSet::iterator i = // Этап 1: поиск изменяемого элемента
se.find(selectedID);
if (i != se.end) {
Employee e(*i); //Этап 2: копирование элемента
se.erase(i++); // Этап 3: удаление элемента.
// Увеличение итератора
// сохраняет его
// действительным (см. совет 9)
e.setTitle("Corporate Deity"); // Этап 4: модификация копии
se.insert(i, е); // Этап 5: вставка нового значения.
// Рекомендуемая позиция совпадает
// с позицией исходного элемента
}
Итак, при изменении «на месте» элементов контейнеров set
и multiset
следует помнить, что за сохранение порядка сортировки отвечает программист.
Совет 23. Рассмотрите возможность замены ассоциативных контейнеров сортированными векторами
Многие программисты STL, столкнувшись с необходимостью структуры данных с быстрым поиском, немедленно выбирают стандартные ассоциативные контейнеры set , multiset , map и multimap
. В этом выборе нет ничего плохого, но он не исчерпывает всех возможных вариантов. Если скорость поиска действительно важна, подумайте об использовании нестандартных хэшированных контейнеров (см. совет 25). При правильном выборе хэш-функций хэшированные контейнеры могут обеспечить поиск с постоянным временем (а при неправильном выборе хэш-функций или недостаточном размере таблиц быстродействие заметно снижается, но на практике это встречается относительно редко). Во многих случаях предполагаемое постоянное время поиска превосходит гарантированное логарифмическое время, характерное для контейнеров set
, map
и их multi
-аналогов.
Даже если гарантированное логарифмическое время поиска вас устраивает, стандартные ассоциативные контейнеры не всегда являются лучшим выбором. Как ни странно, стандартные ассоциативные контейнеры по быстродействию нередко уступают банальному контейнеру vector
. Чтобы эффективно использовать STL, необходимо понимать, в каких случаях vector
превосходит стандартные ассоциативные контейнеры по скорости поиска.
Стандартные ассоциативные контейнеры обычно реализуются в виде сбалансированных бинарных деревьев. Сбалансированное бинарное дерево представляет собой структуру данных, оптимизированную для комбинированных операций вставки, удаления и поиска. Другими словами, оно предназначено для приложений, которые вставляют в контейнер несколько элементов, затем производят поиск, потом вставляют еще несколько элементов, затем что-то удаляют, снова возвращаются к удалению или вставке и т. д. Главной особенностью этой последовательности событий является чередование операций вставки, удаления и поиска. В общем случае невозможно предсказать следующую операцию, выполняемую с деревом.
Во многих приложениях структуры данных используются не столь непредсказуемо. Операции со структурами данных делятся на три раздельные фазы.
1. Подготовка. Создание структуры данных и вставка большого количества элементов. В этой фазе со структурой данных выполняются только операции вставки и удаления. Поиск выполняется редко или полностью отсутствует.
2. Поиск. Выборка нужных данных из структуры. В этой фазе выполняются только операции поиска. Вставка и удаление выполняются редко или полностью отсутствуют.
3. Реорганизация. Модификация содержимого структуры данных (возможно, со стиранием всего текущего содержимого и вставкой новых элементов). По составу выполняемых операций данная фаза эквивалентна фазе 1. После ее завершения приложение возвращается к фазе 2.