Ассоциативные контейнеры C++ обычно основаны на реализациях красно-черного дерева (например, STL, Boost.Intrusive ассоциативные контейнеры). Однако есть и другие интересные структуры данных, которые предлагают некоторые преимущества (а также недостатки).
Деревья Splay — это саморегулирующиеся деревья двоичного поиска, обычно используемые в кэшах, распределителях памяти и других приложениях, потому что деревья Splay имеют «эффект кэширования»: недавно доступные элементы имеют лучшее время доступа, чем элементы, доступные реже. Для получения дополнительной информации о деревьях сплея см.соответствующую запись Википедии.
Навязчивыйпредлагает 3 контейнера на основе деревьев сплей:<splay_set>,<splay_multiset>и<splaytree>. Первые два похожи на<set>или<multiset>, а последний представляет собой обобщение, которое предлагает функции как для вставки уникальных, так и нескольких ключей.
Память над этими контейнерами с Boost. Навязчивые крючки обычно составляют 3 указателя. Пустой, непостоянный размер игрового контейнера также имеет размер 3 указателя.
Назойливые контейнеры на основе дерева Splay имеют логарифмическую сложность во многих операциях, таких как поиски, вставки, стирания и т. Д., Но если некоторые элементы чаще доступны, чем другие, деревья Splay выполняют более быстрый поиск, чем эквивалентные сбалансированные бинарные деревья (например, красно-черные деревья).
Эффект кэширования, предлагаемый сплей-деревьями, имеет свою цену: дерево должно быть сбалансировано при поиске элемента. Для поддержания правильности и гарантии безопасности потока этот эффект кэширования не обновляется, когда называются конст-версии поисковых функций, таких как<find()>,<lower_bound()>,<upper_bound()>,<equal_range()>,<count()>. Это означает, что использование ассоциативных контейнеров на основе splay-tree в качестве замены<set>/<multiset>, специально для функций поиска const, может не привести к желаемым улучшениям производительности.
Если поиск элементов рандомизирован, дерево будет постоянно уравновешено, не воспользовавшись эффектом кэша, поэтому деревья сплея могут обеспечить худшую производительность, чем другие сбалансированные деревья, для нескольких шаблонов поиска.
<base_hook<classHook>>/<member_hook<classT,classHook,HookT::*PtrToMember>>/<value_traits<classValueTraits>>: Чтобы указать тип крючка или характеристики значения, используемые для настройки контейнера. (Чтобы узнать о ценностных чертах, перейдите в разделКонтейнеры с пользовательскими ValueTraits.)
<constant_time_size<boolEnabled>>: Для активации постоянной работы<size()>. Дефолт:<constant_time_size<true>>
<size_type<boolEnabled>>: Указать тип, который будет использоваться для хранения размера контейнера. Дефолт:<size_type<std::size_t>>
Также они могут получить дополнительную опцию:
<compare<classCompare>>: Функция сравнения для объектов, которые вставляются в контейнеры. Сравнительный функтор должен вызывать строгий слабый порядок. Дефолт:<compare<std::less<key_type>>>
<key_of_value<classKeyOfValueFunctionObject>>: Объект функции, который будет определять<key_type>типа значения, которое должно храниться. Этот тип позволит использовать картографический интерфейс.Карта и многокарточный интерфейс с множеством и множествомдля деталей. По умолчанию<key_type>равно<value_type>(набороподобный интерфейс).
Теперь рассмотрим небольшой пример с использованием контейнеров<splay_set>/<splay_multiset>:
#include<boost/intrusive/splay_set.hpp>#include<vector>#include<functional>usingnamespaceboost::intrusive;classmytag;classMyClass:publicbs_set_base_hook<>{intint_;public://This is a member hookbs_set_member_hook<>member_hook_;MyClass(inti):int_(i){}friendbooloperator<(constMyClass&a,constMyClass&b){returna.int_<b.int_;}friendbooloperator>(constMyClass&a,constMyClass&b){returna.int_>b.int_;}friendbooloperator==(constMyClass&a,constMyClass&b){returna.int_==b.int_;}};//Define a set using the base hook that will store values in reverse ordertypedefsplay_set<MyClass,compare<std::greater<MyClass>>>BaseSplaySet;//Define an multiset using the member hooktypedefmember_hook<MyClass,bs_set_member_hook<>,&MyClass::member_hook_>MemberOption;typedefsplay_multiset<MyClass,MemberOption>MemberSplayMultiset;intmain(){typedefstd::vector<MyClass>::iteratorVectIt;//Create several MyClass objects, each one with a different valuestd::vector<MyClass>values;for(inti=0;i<100;++i)values.push_back(MyClass(i));BaseSplaySetbaseset;MemberSplayMultisetmembermultiset;//Insert values in the containerfor(VectItit(values.begin()),itend(values.end());it!=itend;++it){baseset.insert(*it);membermultiset.insert(*it);}//Now test sets{BaseSplaySet::reverse_iteratorrbit(baseset.rbegin());MemberSplayMultiset::iteratormit(membermultiset.begin());VectItit(values.begin()),itend(values.end());//Test the objects inserted in the base hook setfor(;it!=itend;++it,++rbit){if(&*rbit!=&*it)return1;}//Test the objects inserted in member and binary search hook setsfor(it=values.begin();it!=itend;++it,++mit){if(&*mit!=&*it)return1;}}return0;}
Статья Intrusive splay tree based associative containers: splay_set, splay_multiset and , splay_tree раздела The Boost C++ Libraries BoostBook Documentation Subset Chapter 17. Boost.Intrusive может быть полезна для разработчиков на c++ и boost.
Материалы статей собраны из открытых источников, владелец сайта не претендует на авторство. Там где авторство установить не удалось, материал подаётся без имени автора. В случае если Вы считаете, что Ваши права нарушены, пожалуйста, свяжитесь с владельцем сайта.