Предыдущие ответы касаются только альтернатив дерева, и красный черный цвет, вероятно, остается только по историческим причинам.
Почему не хеш-таблица?
Тип требует, чтобы <
оператор (сравнение) использовался как ключ в дереве. Однако для хеш-таблиц требуется, чтобы для каждого типа ключа была определена hash
функция. Соблюдение минимальных требований к типам очень важно для общего программирования, поэтому вы можете использовать его с самыми разными типами и алгоритмами.
Создание хорошей хеш-таблицы требует глубокого знания контекста, в котором она будет использоваться. Должен ли он использовать открытую адресацию или связанную цепочку? Какие уровни нагрузки следует принять перед изменением размера? Следует ли использовать дорогой хеш, который избегает столкновений, или грубый и быстрый?
Так как STL не может предвидеть, какой вариант является лучшим для вашего приложения, по умолчанию он должен быть более гибким. Деревья "просто работают" и хорошо масштабируются.
(C ++ 11 действительно добавил хеш-таблицы с помощью unordered_map
. Как видно из документации, для настройки многих из этих параметров требуется настройка политик.)
А как насчет других деревьев?
Красные Черные деревья предлагают быстрый поиск и являются самобалансирующимися, в отличие от BST. Другой пользователь указал на свои преимущества перед самобалансирующимся деревом AVL.
Александр Степанов (создатель STL) сказал, что он будет использовать дерево B * вместо красно-черного дерева, если он std::map
снова напишет , потому что оно более дружественно для современных кэшей памяти.
Одним из самых больших изменений с тех пор стал рост кешей. Промахи в кеше очень дороги, так что местность ссылок сейчас гораздо важнее. Структуры данных на основе узлов, которые имеют низкую локальность ссылок, имеют гораздо меньше смысла. Если бы я проектировал STL сегодня, у меня был бы другой набор контейнеров. Например, B * -дерево в памяти является гораздо лучшим выбором, чем красно-черное дерево для реализации ассоциативного контейнера. - Александр Степанов
Должны ли карты всегда использовать деревья?
Другой возможной реализацией карт будет сортированный вектор (сортировка вставкой) и бинарный поиск. Это будет хорошо работать для контейнеров, которые не часто изменяются, но часто запрашиваются. Я часто делаю это в C, как qsort
и bsearch
встроены.
Мне даже нужно использовать карту?
Соображения о кеше означают, что редко имеет смысл использовать std::list
или std::deque
перезаписывать std:vector
даже те ситуации, которым нас учили в школе (например, удаление элемента из середины списка). Применяя те же аргументы, использование цикла for для линейного поиска по списку часто более эффективно и чище, чем построение карты для нескольких поисков.
Конечно, выбор читаемого контейнера обычно важнее производительности.