В STL конкретная реализация бинарного дерева представлена структурой set, поддерживающей упорядоченное множество уникальных элементов.
#Основные операции
Структуру set<T> можно объявить от любого типа, для которого реализован оператор сравнения — в частности, для пар и тюплов он реализован автоматически как лексикографическая сортировка.
set<int> s;
s.insert(3); // s = {3}
s.insert(2); // s = {2, 3}
s.size(); // вернет |s| = 2
s.insert(3); // 3 не будет добавлено ещё раз, так как уже присутствует в множестве
s.size(); // |s| = 2
// присутствует ли в множестве элемент:
s.count(3); // вернет 1
s.count(5); // вернет 0
s.erase(3); // s = {2}
s.insert(6); // s = {2, 6}
Так как set реализован как сбалансированное двоичное дерево поиска — а конкретно как красно-черное дерево — все операции с его элементами работают за .
#Итераторы
Также set, как и все контейнеры STL, поддерживает итераторы.
Начало set (наименьший элемент) можно получить через .begin(), конец — через .end(). Обратите внимание, что .end(), как и все итераторы, указывает на конец полуинтервала — то есть на несуществующий элемент, идущий после последнего.
auto it = s.find(2); // возвращает итератор на элемент или `end`, если элемента нет
++it; // найти следующий элемент
int x = *it; // x = 6
s.lower_bound(1); // вернет 2, так как это первый элемент >= 1
s.upper_bound(2); // вернет 6, так как это первый элемент > 2
auto it = s.upper_bound(10);
if (it == s.end()) {
// аккуратно: если разыменуете it, получите undefined behavior!
}
// вывод всех элементов сета в порядке возрастания с использованием итераторов
for (auto it = s.begin(); it != s.end(); ++it)
cout << *it << " ";
// но для таких целей лучше использовать range-based for loop
for (int x : s)
cout << x << " ";
Инкремент и декремент итераторов работает за логарифмические время.
#Связанные структуры
В STL есть несколько структур со схожей функциональностью:
mapассоциирует с ключами значения и позволяет получать их как из бесконечных массивов:m[x] = y.multisetподдерживает дубликаты элементов..count(x)у него возвращает количество элементов с заданным ключом, а не просто 0 или 1. Его можно реализовать какmap, в котором в качестве значений хранятся количества элементов.multimapвозвращает по ключу много различных значений вместо одного и позволяет итерироваться по ним (то же самое, что использовать). Его можно реализовать какmap<A, vector<B>>.
Также у всех этих контейнеров есть аналоги, работающие на хеш-таблицах вместо деревьев: unordered_set, unordered_map, unordered_multiset и unordered_multimap. В них поиск, удаление и вставка в среднем работают за константное время, но нет lower_bound и упорядоченного итерирования.