bstree_algorithms.hpp 72 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988
  1. /////////////////////////////////////////////////////////////////////////////
  2. //
  3. // (C) Copyright Ion Gaztanaga 2007-2013
  4. //
  5. // Distributed under the Boost Software License, Version 1.0.
  6. // (See accompanying file LICENSE_1_0.txt or copy at
  7. // http://www.boost.org/LICENSE_1_0.txt)
  8. //
  9. // See http://www.boost.org/libs/intrusive for documentation.
  10. //
  11. /////////////////////////////////////////////////////////////////////////////
  12. #ifndef BOOST_INTRUSIVE_BSTREE_ALGORITHMS_HPP
  13. #define BOOST_INTRUSIVE_BSTREE_ALGORITHMS_HPP
  14. #include <boost/intrusive/detail/config_begin.hpp>
  15. #include <boost/intrusive/detail/assert.hpp>
  16. #include <boost/intrusive/intrusive_fwd.hpp>
  17. #include <cstddef>
  18. #include <boost/intrusive/detail/utilities.hpp>
  19. #include <boost/intrusive/pointer_traits.hpp>
  20. namespace boost {
  21. namespace intrusive {
  22. /// @cond
  23. //! This type is the information that will be filled by insert_unique_check
  24. template <class NodePtr>
  25. struct insert_commit_data_t
  26. {
  27. insert_commit_data_t()
  28. : link_left(false)
  29. , node()
  30. {}
  31. bool link_left;
  32. NodePtr node;
  33. };
  34. template <class NodePtr>
  35. struct data_for_rebalance_t
  36. {
  37. NodePtr x;
  38. NodePtr x_parent;
  39. NodePtr y;
  40. };
  41. /// @endcond
  42. //! This is an implementation of a binary search tree.
  43. //! A node in the search tree has references to its children and its parent. This
  44. //! is to allow traversal of the whole tree from a given node making the
  45. //! implementation of iterator a pointer to a node.
  46. //! At the top of the tree a node is used specially. This node's parent pointer
  47. //! is pointing to the root of the tree. Its left pointer points to the
  48. //! leftmost node in the tree and the right pointer to the rightmost one.
  49. //! This node is used to represent the end-iterator.
  50. //!
  51. //! +---------+
  52. //! header------------------------------>| |
  53. //! | |
  54. //! +----------(left)--------| |--------(right)---------+
  55. //! | +---------+ |
  56. //! | | |
  57. //! | | (parent) |
  58. //! | | |
  59. //! | | |
  60. //! | +---------+ |
  61. //! root of tree ..|......................> | | |
  62. //! | | D | |
  63. //! | | | |
  64. //! | +-------+---------+-------+ |
  65. //! | | | |
  66. //! | | | |
  67. //! | | | |
  68. //! | | | |
  69. //! | | | |
  70. //! | +---------+ +---------+ |
  71. //! | | | | | |
  72. //! | | B | | F | |
  73. //! | | | | | |
  74. //! | +--+---------+--+ +--+---------+--+ |
  75. //! | | | | | |
  76. //! | | | | | |
  77. //! | | | | | |
  78. //! | +---+-----+ +-----+---+ +---+-----+ +-----+---+ |
  79. //! +-->| | | | | | | |<--+
  80. //! | A | | C | | E | | G |
  81. //! | | | | | | | |
  82. //! +---------+ +---------+ +---------+ +---------+
  83. //!
  84. //! bstree_algorithms is configured with a NodeTraits class, which encapsulates the
  85. //! information about the node to be manipulated. NodeTraits must support the
  86. //! following interface:
  87. //!
  88. //! <b>Typedefs</b>:
  89. //!
  90. //! <tt>node</tt>: The type of the node that forms the binary search tree
  91. //!
  92. //! <tt>node_ptr</tt>: A pointer to a node
  93. //!
  94. //! <tt>const_node_ptr</tt>: A pointer to a const node
  95. //!
  96. //! <b>Static functions</b>:
  97. //!
  98. //! <tt>static node_ptr get_parent(const_node_ptr n);</tt>
  99. //!
  100. //! <tt>static void set_parent(node_ptr n, node_ptr parent);</tt>
  101. //!
  102. //! <tt>static node_ptr get_left(const_node_ptr n);</tt>
  103. //!
  104. //! <tt>static void set_left(node_ptr n, node_ptr left);</tt>
  105. //!
  106. //! <tt>static node_ptr get_right(const_node_ptr n);</tt>
  107. //!
  108. //! <tt>static void set_right(node_ptr n, node_ptr right);</tt>
  109. template<class NodeTraits>
  110. class bstree_algorithms
  111. {
  112. public:
  113. typedef typename NodeTraits::node node;
  114. typedef NodeTraits node_traits;
  115. typedef typename NodeTraits::node_ptr node_ptr;
  116. typedef typename NodeTraits::const_node_ptr const_node_ptr;
  117. typedef insert_commit_data_t<node_ptr> insert_commit_data;
  118. typedef data_for_rebalance_t<node_ptr> data_for_rebalance;
  119. /// @cond
  120. private:
  121. template<class Disposer>
  122. struct dispose_subtree_disposer
  123. {
  124. dispose_subtree_disposer(Disposer &disp, const node_ptr & subtree)
  125. : disposer_(&disp), subtree_(subtree)
  126. {}
  127. void release()
  128. { disposer_ = 0; }
  129. ~dispose_subtree_disposer()
  130. {
  131. if(disposer_){
  132. dispose_subtree(subtree_, *disposer_);
  133. }
  134. }
  135. Disposer *disposer_;
  136. const node_ptr subtree_;
  137. };
  138. /// @endcond
  139. public:
  140. //! <b>Requires</b>: 'header' is the header node of a tree.
  141. //!
  142. //! <b>Effects</b>: Returns the first node of the tree, the header if the tree is empty.
  143. //!
  144. //! <b>Complexity</b>: Constant time.
  145. //!
  146. //! <b>Throws</b>: Nothing.
  147. static node_ptr begin_node(const const_node_ptr & header)
  148. { return node_traits::get_left(header); }
  149. //! <b>Requires</b>: 'header' is the header node of a tree.
  150. //!
  151. //! <b>Effects</b>: Returns the header of the tree.
  152. //!
  153. //! <b>Complexity</b>: Constant time.
  154. //!
  155. //! <b>Throws</b>: Nothing.
  156. static node_ptr end_node(const const_node_ptr & header)
  157. { return detail::uncast(header); }
  158. //! <b>Requires</b>: 'node' is a node of the tree or an node initialized
  159. //! by init(...) or init_node.
  160. //!
  161. //! <b>Effects</b>: Returns true if the node is initialized by init() or init_node().
  162. //!
  163. //! <b>Complexity</b>: Constant time.
  164. //!
  165. //! <b>Throws</b>: Nothing.
  166. static bool unique(const const_node_ptr & node)
  167. { return !NodeTraits::get_parent(node); }
  168. //! <b>Requires</b>: 'node' is a node of the tree or a header node.
  169. //!
  170. //! <b>Effects</b>: Returns the header of the tree.
  171. //!
  172. //! <b>Complexity</b>: Logarithmic.
  173. //!
  174. //! <b>Throws</b>: Nothing.
  175. static node_ptr get_header(const const_node_ptr & node)
  176. {
  177. node_ptr n(detail::uncast(node));
  178. node_ptr p(NodeTraits::get_parent(node));
  179. //If p is null, then n is the header of an empty tree
  180. if(p){
  181. //Non-empty tree, check if n is neither root nor header
  182. node_ptr pp(NodeTraits::get_parent(p));
  183. //If granparent is not equal to n, then n is neither root nor header,
  184. //the try the fast path
  185. if(n != pp){
  186. do{
  187. n = p;
  188. p = pp;
  189. pp = NodeTraits::get_parent(pp);
  190. }while(n != pp);
  191. n = p;
  192. }
  193. //Check if n is root or header when size() > 0
  194. else if(!is_header(n)){
  195. n = p;
  196. }
  197. }
  198. return n;
  199. /*
  200. node_ptr h = detail::uncast(node);
  201. node_ptr p = NodeTraits::get_parent(node);
  202. if(p){
  203. while(!is_header(p))
  204. p = NodeTraits::get_parent(p);
  205. return p;
  206. }
  207. else{
  208. return h;
  209. }*/
  210. }
  211. //! <b>Requires</b>: node1 and node2 can't be header nodes
  212. //! of two trees.
  213. //!
  214. //! <b>Effects</b>: Swaps two nodes. After the function node1 will be inserted
  215. //! in the position node2 before the function. node2 will be inserted in the
  216. //! position node1 had before the function.
  217. //!
  218. //! <b>Complexity</b>: Logarithmic.
  219. //!
  220. //! <b>Throws</b>: Nothing.
  221. //!
  222. //! <b>Note</b>: This function will break container ordering invariants if
  223. //! node1 and node2 are not equivalent according to the ordering rules.
  224. //!
  225. //!Experimental function
  226. static void swap_nodes(const node_ptr & node1, const node_ptr & node2)
  227. {
  228. if(node1 == node2)
  229. return;
  230. node_ptr header1(get_header(node1)), header2(get_header(node2));
  231. swap_nodes(node1, header1, node2, header2);
  232. }
  233. //! <b>Requires</b>: node1 and node2 can't be header nodes
  234. //! of two trees with header header1 and header2.
  235. //!
  236. //! <b>Effects</b>: Swaps two nodes. After the function node1 will be inserted
  237. //! in the position node2 before the function. node2 will be inserted in the
  238. //! position node1 had before the function.
  239. //!
  240. //! <b>Complexity</b>: Constant.
  241. //!
  242. //! <b>Throws</b>: Nothing.
  243. //!
  244. //! <b>Note</b>: This function will break container ordering invariants if
  245. //! node1 and node2 are not equivalent according to the ordering rules.
  246. //!
  247. //!Experimental function
  248. static void swap_nodes(const node_ptr & node1, const node_ptr & header1, const node_ptr & node2, const node_ptr & header2)
  249. {
  250. if(node1 == node2)
  251. return;
  252. //node1 and node2 must not be header nodes
  253. //BOOST_INTRUSIVE_INVARIANT_ASSERT((header1 != node1 && header2 != node2));
  254. if(header1 != header2){
  255. //Update header1 if necessary
  256. if(node1 == NodeTraits::get_left(header1)){
  257. NodeTraits::set_left(header1, node2);
  258. }
  259. if(node1 == NodeTraits::get_right(header1)){
  260. NodeTraits::set_right(header1, node2);
  261. }
  262. if(node1 == NodeTraits::get_parent(header1)){
  263. NodeTraits::set_parent(header1, node2);
  264. }
  265. //Update header2 if necessary
  266. if(node2 == NodeTraits::get_left(header2)){
  267. NodeTraits::set_left(header2, node1);
  268. }
  269. if(node2 == NodeTraits::get_right(header2)){
  270. NodeTraits::set_right(header2, node1);
  271. }
  272. if(node2 == NodeTraits::get_parent(header2)){
  273. NodeTraits::set_parent(header2, node1);
  274. }
  275. }
  276. else{
  277. //If both nodes are from the same tree
  278. //Update header if necessary
  279. if(node1 == NodeTraits::get_left(header1)){
  280. NodeTraits::set_left(header1, node2);
  281. }
  282. else if(node2 == NodeTraits::get_left(header2)){
  283. NodeTraits::set_left(header2, node1);
  284. }
  285. if(node1 == NodeTraits::get_right(header1)){
  286. NodeTraits::set_right(header1, node2);
  287. }
  288. else if(node2 == NodeTraits::get_right(header2)){
  289. NodeTraits::set_right(header2, node1);
  290. }
  291. if(node1 == NodeTraits::get_parent(header1)){
  292. NodeTraits::set_parent(header1, node2);
  293. }
  294. else if(node2 == NodeTraits::get_parent(header2)){
  295. NodeTraits::set_parent(header2, node1);
  296. }
  297. //Adjust data in nodes to be swapped
  298. //so that final link swap works as expected
  299. if(node1 == NodeTraits::get_parent(node2)){
  300. NodeTraits::set_parent(node2, node2);
  301. if(node2 == NodeTraits::get_right(node1)){
  302. NodeTraits::set_right(node1, node1);
  303. }
  304. else{
  305. NodeTraits::set_left(node1, node1);
  306. }
  307. }
  308. else if(node2 == NodeTraits::get_parent(node1)){
  309. NodeTraits::set_parent(node1, node1);
  310. if(node1 == NodeTraits::get_right(node2)){
  311. NodeTraits::set_right(node2, node2);
  312. }
  313. else{
  314. NodeTraits::set_left(node2, node2);
  315. }
  316. }
  317. }
  318. //Now swap all the links
  319. node_ptr temp;
  320. //swap left link
  321. temp = NodeTraits::get_left(node1);
  322. NodeTraits::set_left(node1, NodeTraits::get_left(node2));
  323. NodeTraits::set_left(node2, temp);
  324. //swap right link
  325. temp = NodeTraits::get_right(node1);
  326. NodeTraits::set_right(node1, NodeTraits::get_right(node2));
  327. NodeTraits::set_right(node2, temp);
  328. //swap parent link
  329. temp = NodeTraits::get_parent(node1);
  330. NodeTraits::set_parent(node1, NodeTraits::get_parent(node2));
  331. NodeTraits::set_parent(node2, temp);
  332. //Now adjust adjacent nodes for newly inserted node 1
  333. if((temp = NodeTraits::get_left(node1))){
  334. NodeTraits::set_parent(temp, node1);
  335. }
  336. if((temp = NodeTraits::get_right(node1))){
  337. NodeTraits::set_parent(temp, node1);
  338. }
  339. if((temp = NodeTraits::get_parent(node1)) &&
  340. //The header has been already updated so avoid it
  341. temp != header2){
  342. if(NodeTraits::get_left(temp) == node2){
  343. NodeTraits::set_left(temp, node1);
  344. }
  345. if(NodeTraits::get_right(temp) == node2){
  346. NodeTraits::set_right(temp, node1);
  347. }
  348. }
  349. //Now adjust adjacent nodes for newly inserted node 2
  350. if((temp = NodeTraits::get_left(node2))){
  351. NodeTraits::set_parent(temp, node2);
  352. }
  353. if((temp = NodeTraits::get_right(node2))){
  354. NodeTraits::set_parent(temp, node2);
  355. }
  356. if((temp = NodeTraits::get_parent(node2)) &&
  357. //The header has been already updated so avoid it
  358. temp != header1){
  359. if(NodeTraits::get_left(temp) == node1){
  360. NodeTraits::set_left(temp, node2);
  361. }
  362. if(NodeTraits::get_right(temp) == node1){
  363. NodeTraits::set_right(temp, node2);
  364. }
  365. }
  366. }
  367. //! <b>Requires</b>: node_to_be_replaced must be inserted in a tree
  368. //! and new_node must not be inserted in a tree.
  369. //!
  370. //! <b>Effects</b>: Replaces node_to_be_replaced in its position in the
  371. //! tree with new_node. The tree does not need to be rebalanced
  372. //!
  373. //! <b>Complexity</b>: Logarithmic.
  374. //!
  375. //! <b>Throws</b>: Nothing.
  376. //!
  377. //! <b>Note</b>: This function will break container ordering invariants if
  378. //! new_node is not equivalent to node_to_be_replaced according to the
  379. //! ordering rules. This function is faster than erasing and inserting
  380. //! the node, since no rebalancing and comparison is needed. Experimental function
  381. static void replace_node(const node_ptr & node_to_be_replaced, const node_ptr & new_node)
  382. {
  383. if(node_to_be_replaced == new_node)
  384. return;
  385. replace_node(node_to_be_replaced, get_header(node_to_be_replaced), new_node);
  386. }
  387. //! <b>Requires</b>: node_to_be_replaced must be inserted in a tree
  388. //! with header "header" and new_node must not be inserted in a tree.
  389. //!
  390. //! <b>Effects</b>: Replaces node_to_be_replaced in its position in the
  391. //! tree with new_node. The tree does not need to be rebalanced
  392. //!
  393. //! <b>Complexity</b>: Constant.
  394. //!
  395. //! <b>Throws</b>: Nothing.
  396. //!
  397. //! <b>Note</b>: This function will break container ordering invariants if
  398. //! new_node is not equivalent to node_to_be_replaced according to the
  399. //! ordering rules. This function is faster than erasing and inserting
  400. //! the node, since no rebalancing or comparison is needed. Experimental function
  401. static void replace_node(const node_ptr & node_to_be_replaced, const node_ptr & header, const node_ptr & new_node)
  402. {
  403. if(node_to_be_replaced == new_node)
  404. return;
  405. //Update header if necessary
  406. if(node_to_be_replaced == NodeTraits::get_left(header)){
  407. NodeTraits::set_left(header, new_node);
  408. }
  409. if(node_to_be_replaced == NodeTraits::get_right(header)){
  410. NodeTraits::set_right(header, new_node);
  411. }
  412. if(node_to_be_replaced == NodeTraits::get_parent(header)){
  413. NodeTraits::set_parent(header, new_node);
  414. }
  415. //Now set data from the original node
  416. node_ptr temp;
  417. NodeTraits::set_left(new_node, NodeTraits::get_left(node_to_be_replaced));
  418. NodeTraits::set_right(new_node, NodeTraits::get_right(node_to_be_replaced));
  419. NodeTraits::set_parent(new_node, NodeTraits::get_parent(node_to_be_replaced));
  420. //Now adjust adjacent nodes for newly inserted node
  421. if((temp = NodeTraits::get_left(new_node))){
  422. NodeTraits::set_parent(temp, new_node);
  423. }
  424. if((temp = NodeTraits::get_right(new_node))){
  425. NodeTraits::set_parent(temp, new_node);
  426. }
  427. if((temp = NodeTraits::get_parent(new_node)) &&
  428. //The header has been already updated so avoid it
  429. temp != header){
  430. if(NodeTraits::get_left(temp) == node_to_be_replaced){
  431. NodeTraits::set_left(temp, new_node);
  432. }
  433. if(NodeTraits::get_right(temp) == node_to_be_replaced){
  434. NodeTraits::set_right(temp, new_node);
  435. }
  436. }
  437. }
  438. //! <b>Requires</b>: 'node' is a node from the tree except the header.
  439. //!
  440. //! <b>Effects</b>: Returns the next node of the tree.
  441. //!
  442. //! <b>Complexity</b>: Average constant time.
  443. //!
  444. //! <b>Throws</b>: Nothing.
  445. static node_ptr next_node(const node_ptr & node)
  446. {
  447. node_ptr p_right(NodeTraits::get_right(node));
  448. if(p_right){
  449. return minimum(p_right);
  450. }
  451. else {
  452. node_ptr p(node);
  453. node_ptr x = NodeTraits::get_parent(p);
  454. while(p == NodeTraits::get_right(x)){
  455. p = x;
  456. x = NodeTraits::get_parent(x);
  457. }
  458. return NodeTraits::get_right(p) != x ? x : detail::uncast(p);
  459. }
  460. }
  461. //! <b>Requires</b>: 'node' is a node from the tree except the leftmost node.
  462. //!
  463. //! <b>Effects</b>: Returns the previous node of the tree.
  464. //!
  465. //! <b>Complexity</b>: Average constant time.
  466. //!
  467. //! <b>Throws</b>: Nothing.
  468. static node_ptr prev_node(const node_ptr & node)
  469. {
  470. if(is_header(node)){
  471. return NodeTraits::get_right(node);
  472. //return maximum(NodeTraits::get_parent(node));
  473. }
  474. else if(NodeTraits::get_left(node)){
  475. return maximum(NodeTraits::get_left(node));
  476. }
  477. else {
  478. node_ptr p(node);
  479. node_ptr x = NodeTraits::get_parent(p);
  480. while(p == NodeTraits::get_left(x)){
  481. p = x;
  482. x = NodeTraits::get_parent(x);
  483. }
  484. return x;
  485. }
  486. }
  487. //! <b>Requires</b>: 'node' is a node of a tree but not the header.
  488. //!
  489. //! <b>Effects</b>: Returns the minimum node of the subtree starting at p.
  490. //!
  491. //! <b>Complexity</b>: Logarithmic to the size of the subtree.
  492. //!
  493. //! <b>Throws</b>: Nothing.
  494. static node_ptr minimum (node_ptr node)
  495. {
  496. for(node_ptr p_left = NodeTraits::get_left(node)
  497. ;p_left
  498. ;p_left = NodeTraits::get_left(node)){
  499. node = p_left;
  500. }
  501. return node;
  502. }
  503. //! <b>Requires</b>: 'node' is a node of a tree but not the header.
  504. //!
  505. //! <b>Effects</b>: Returns the maximum node of the subtree starting at p.
  506. //!
  507. //! <b>Complexity</b>: Logarithmic to the size of the subtree.
  508. //!
  509. //! <b>Throws</b>: Nothing.
  510. static node_ptr maximum(node_ptr node)
  511. {
  512. for(node_ptr p_right = NodeTraits::get_right(node)
  513. ;p_right
  514. ;p_right = NodeTraits::get_right(node)){
  515. node = p_right;
  516. }
  517. return node;
  518. }
  519. //! <b>Requires</b>: 'node' must not be part of any tree.
  520. //!
  521. //! <b>Effects</b>: After the function unique(node) == true.
  522. //!
  523. //! <b>Complexity</b>: Constant.
  524. //!
  525. //! <b>Throws</b>: Nothing.
  526. //!
  527. //! <b>Nodes</b>: If node is inserted in a tree, this function corrupts the tree.
  528. static void init(const node_ptr & node)
  529. {
  530. NodeTraits::set_parent(node, node_ptr());
  531. NodeTraits::set_left(node, node_ptr());
  532. NodeTraits::set_right(node, node_ptr());
  533. };
  534. //! <b>Effects</b>: Returns true if node is in the same state as if called init(node)
  535. //!
  536. //! <b>Complexity</b>: Constant.
  537. //!
  538. //! <b>Throws</b>: Nothing.
  539. static bool inited(const const_node_ptr & node)
  540. {
  541. return !NodeTraits::get_parent(node) &&
  542. !NodeTraits::get_left(node) &&
  543. !NodeTraits::get_right(node) ;
  544. };
  545. //! <b>Requires</b>: node must not be part of any tree.
  546. //!
  547. //! <b>Effects</b>: Initializes the header to represent an empty tree.
  548. //! unique(header) == true.
  549. //!
  550. //! <b>Complexity</b>: Constant.
  551. //!
  552. //! <b>Throws</b>: Nothing.
  553. //!
  554. //! <b>Nodes</b>: If node is inserted in a tree, this function corrupts the tree.
  555. static void init_header(const node_ptr & header)
  556. {
  557. NodeTraits::set_parent(header, node_ptr());
  558. NodeTraits::set_left(header, header);
  559. NodeTraits::set_right(header, header);
  560. }
  561. //! <b>Requires</b>: "disposer" must be an object function
  562. //! taking a node_ptr parameter and shouldn't throw.
  563. //!
  564. //! <b>Effects</b>: Empties the target tree calling
  565. //! <tt>void disposer::operator()(const node_ptr &)</tt> for every node of the tree
  566. //! except the header.
  567. //!
  568. //! <b>Complexity</b>: Linear to the number of element of the source tree plus the.
  569. //! number of elements of tree target tree when calling this function.
  570. //!
  571. //! <b>Throws</b>: If cloner functor throws. If this happens target nodes are disposed.
  572. template<class Disposer>
  573. static void clear_and_dispose(const node_ptr & header, Disposer disposer)
  574. {
  575. node_ptr source_root = NodeTraits::get_parent(header);
  576. if(!source_root)
  577. return;
  578. dispose_subtree(source_root, disposer);
  579. init_header(header);
  580. }
  581. //! <b>Requires</b>: header is the header of a tree.
  582. //!
  583. //! <b>Effects</b>: Unlinks the leftmost node from the tree, and
  584. //! updates the header link to the new leftmost node.
  585. //!
  586. //! <b>Complexity</b>: Average complexity is constant time.
  587. //!
  588. //! <b>Throws</b>: Nothing.
  589. //!
  590. //! <b>Notes</b>: This function breaks the tree and the tree can
  591. //! only be used for more unlink_leftmost_without_rebalance calls.
  592. //! This function is normally used to achieve a step by step
  593. //! controlled destruction of the tree.
  594. static node_ptr unlink_leftmost_without_rebalance(const node_ptr & header)
  595. {
  596. node_ptr leftmost = NodeTraits::get_left(header);
  597. if (leftmost == header)
  598. return node_ptr();
  599. node_ptr leftmost_parent(NodeTraits::get_parent(leftmost));
  600. node_ptr leftmost_right (NodeTraits::get_right(leftmost));
  601. bool is_root = leftmost_parent == header;
  602. if (leftmost_right){
  603. NodeTraits::set_parent(leftmost_right, leftmost_parent);
  604. NodeTraits::set_left(header, bstree_algorithms::minimum(leftmost_right));
  605. if (is_root)
  606. NodeTraits::set_parent(header, leftmost_right);
  607. else
  608. NodeTraits::set_left(NodeTraits::get_parent(header), leftmost_right);
  609. }
  610. else if (is_root){
  611. NodeTraits::set_parent(header, node_ptr());
  612. NodeTraits::set_left(header, header);
  613. NodeTraits::set_right(header, header);
  614. }
  615. else{
  616. NodeTraits::set_left(leftmost_parent, node_ptr());
  617. NodeTraits::set_left(header, leftmost_parent);
  618. }
  619. return leftmost;
  620. }
  621. //! <b>Requires</b>: node is a node of the tree but it's not the header.
  622. //!
  623. //! <b>Effects</b>: Returns the number of nodes of the subtree.
  624. //!
  625. //! <b>Complexity</b>: Linear time.
  626. //!
  627. //! <b>Throws</b>: Nothing.
  628. static std::size_t size(const const_node_ptr & header)
  629. {
  630. node_ptr beg(begin_node(header));
  631. node_ptr end(end_node(header));
  632. std::size_t i = 0;
  633. for(;beg != end; beg = next_node(beg)) ++i;
  634. return i;
  635. }
  636. //! <b>Requires</b>: header1 and header2 must be the header nodes
  637. //! of two trees.
  638. //!
  639. //! <b>Effects</b>: Swaps two trees. After the function header1 will contain
  640. //! links to the second tree and header2 will have links to the first tree.
  641. //!
  642. //! <b>Complexity</b>: Constant.
  643. //!
  644. //! <b>Throws</b>: Nothing.
  645. static void swap_tree(const node_ptr & header1, const node_ptr & header2)
  646. {
  647. if(header1 == header2)
  648. return;
  649. node_ptr tmp;
  650. //Parent swap
  651. tmp = NodeTraits::get_parent(header1);
  652. NodeTraits::set_parent(header1, NodeTraits::get_parent(header2));
  653. NodeTraits::set_parent(header2, tmp);
  654. //Left swap
  655. tmp = NodeTraits::get_left(header1);
  656. NodeTraits::set_left(header1, NodeTraits::get_left(header2));
  657. NodeTraits::set_left(header2, tmp);
  658. //Right swap
  659. tmp = NodeTraits::get_right(header1);
  660. NodeTraits::set_right(header1, NodeTraits::get_right(header2));
  661. NodeTraits::set_right(header2, tmp);
  662. //Now test parent
  663. node_ptr h1_parent(NodeTraits::get_parent(header1));
  664. if(h1_parent){
  665. NodeTraits::set_parent(h1_parent, header1);
  666. }
  667. else{
  668. NodeTraits::set_left(header1, header1);
  669. NodeTraits::set_right(header1, header1);
  670. }
  671. node_ptr h2_parent(NodeTraits::get_parent(header2));
  672. if(h2_parent){
  673. NodeTraits::set_parent(h2_parent, header2);
  674. }
  675. else{
  676. NodeTraits::set_left(header2, header2);
  677. NodeTraits::set_right(header2, header2);
  678. }
  679. }
  680. //! <b>Requires</b>: p is a node of a tree.
  681. //!
  682. //! <b>Effects</b>: Returns true if p is the header of the tree.
  683. //!
  684. //! <b>Complexity</b>: Constant.
  685. //!
  686. //! <b>Throws</b>: Nothing.
  687. static bool is_header(const const_node_ptr & p)
  688. {
  689. node_ptr p_left (NodeTraits::get_left(p));
  690. node_ptr p_right(NodeTraits::get_right(p));
  691. if(!NodeTraits::get_parent(p) || //Header condition when empty tree
  692. (p_left && p_right && //Header always has leftmost and rightmost
  693. (p_left == p_right || //Header condition when only node
  694. (NodeTraits::get_parent(p_left) != p ||
  695. NodeTraits::get_parent(p_right) != p ))
  696. //When tree size > 1 headers can't be leftmost's
  697. //and rightmost's parent
  698. )){
  699. return true;
  700. }
  701. return false;
  702. }
  703. //! <b>Requires</b>: "header" must be the header node of a tree.
  704. //! KeyNodePtrCompare is a function object that induces a strict weak
  705. //! ordering compatible with the strict weak ordering used to create the
  706. //! the tree. KeyNodePtrCompare can compare KeyType with tree's node_ptrs.
  707. //!
  708. //! <b>Effects</b>: Returns an node_ptr to the element that is equivalent to
  709. //! "key" according to "comp" or "header" if that element does not exist.
  710. //!
  711. //! <b>Complexity</b>: Logarithmic.
  712. //!
  713. //! <b>Throws</b>: If "comp" throws.
  714. template<class KeyType, class KeyNodePtrCompare>
  715. static node_ptr find
  716. (const const_node_ptr & header, const KeyType &key, KeyNodePtrCompare comp)
  717. {
  718. node_ptr end = detail::uncast(header);
  719. node_ptr y = lower_bound(header, key, comp);
  720. return (y == end || comp(key, y)) ? end : y;
  721. }
  722. //! <b>Requires</b>: "header" must be the header node of a tree.
  723. //! KeyNodePtrCompare is a function object that induces a strict weak
  724. //! ordering compatible with the strict weak ordering used to create the
  725. //! the tree. KeyNodePtrCompare can compare KeyType with tree's node_ptrs.
  726. //! 'lower_key' must not be greater than 'upper_key' according to 'comp'. If
  727. //! 'lower_key' == 'upper_key', ('left_closed' || 'right_closed') must be false.
  728. //!
  729. //! <b>Effects</b>: Returns an a pair with the following criteria:
  730. //!
  731. //! first = lower_bound(lower_key) if left_closed, upper_bound(lower_key) otherwise
  732. //!
  733. //! second = upper_bound(upper_key) if right_closed, lower_bound(upper_key) otherwise
  734. //!
  735. //! <b>Complexity</b>: Logarithmic.
  736. //!
  737. //! <b>Throws</b>: If "comp" throws.
  738. //!
  739. //! <b>Note</b>: This function can be more efficient than calling upper_bound
  740. //! and lower_bound for lower_key and upper_key.
  741. //!
  742. //! <b>Note</b>: Experimental function, the interface might change.
  743. template< class KeyType, class KeyNodePtrCompare>
  744. static std::pair<node_ptr, node_ptr> bounded_range
  745. ( const const_node_ptr & header
  746. , const KeyType &lower_key
  747. , const KeyType &upper_key
  748. , KeyNodePtrCompare comp
  749. , bool left_closed
  750. , bool right_closed)
  751. {
  752. node_ptr y = detail::uncast(header);
  753. node_ptr x = NodeTraits::get_parent(header);
  754. while(x){
  755. //If x is less than lower_key the target
  756. //range is on the right part
  757. if(comp(x, lower_key)){
  758. //Check for invalid input range
  759. BOOST_INTRUSIVE_INVARIANT_ASSERT(comp(x, upper_key));
  760. x = NodeTraits::get_right(x);
  761. }
  762. //If the upper_key is less than x, the target
  763. //range is on the left part
  764. else if(comp(upper_key, x)){
  765. //y > upper_key
  766. y = x;
  767. x = NodeTraits::get_left(x);
  768. }
  769. else{
  770. //x is inside the bounded range( x >= lower_key && x <= upper_key),
  771. //so we must split lower and upper searches
  772. //
  773. //Sanity check: if lower_key and upper_key are equal, then both left_closed and right_closed can't be false
  774. BOOST_INTRUSIVE_INVARIANT_ASSERT(left_closed || right_closed || comp(lower_key, x) || comp(x, upper_key));
  775. return std::pair<node_ptr,node_ptr>(
  776. left_closed
  777. //If left_closed, then comp(x, lower_key) is already the lower_bound
  778. //condition so we save one comparison and go to the next level
  779. //following traditional lower_bound algo
  780. ? lower_bound_loop(NodeTraits::get_left(x), x, lower_key, comp)
  781. //If left-open, comp(x, lower_key) is not the upper_bound algo
  782. //condition so we must recheck current 'x' node with upper_bound algo
  783. : upper_bound_loop(x, y, lower_key, comp)
  784. ,
  785. right_closed
  786. //If right_closed, then comp(upper_key, x) is already the upper_bound
  787. //condition so we can save one comparison and go to the next level
  788. //following lower_bound algo
  789. ? upper_bound_loop(NodeTraits::get_right(x), y, upper_key, comp)
  790. //If right-open, comp(upper_key, x) is not the lower_bound algo
  791. //condition so we must recheck current 'x' node with lower_bound algo
  792. : lower_bound_loop(x, y, upper_key, comp)
  793. );
  794. }
  795. }
  796. return std::pair<node_ptr,node_ptr> (y, y);
  797. }
  798. //! <b>Requires</b>: "header" must be the header node of a tree.
  799. //! KeyNodePtrCompare is a function object that induces a strict weak
  800. //! ordering compatible with the strict weak ordering used to create the
  801. //! the tree. KeyNodePtrCompare can compare KeyType with tree's node_ptrs.
  802. //!
  803. //! <b>Effects</b>: Returns the number of elements with a key equivalent to "key"pair of node_ptr delimiting a range containing
  804. //! according to "comp".
  805. //!
  806. //! <b>Complexity</b>: Logarithmic.
  807. //!
  808. //! <b>Throws</b>: If "comp" throws.
  809. template<class KeyType, class KeyNodePtrCompare>
  810. static std::size_t count
  811. (const const_node_ptr & header, const KeyType &key, KeyNodePtrCompare comp)
  812. {
  813. std::pair<node_ptr, node_ptr> ret = equal_range(header, key, comp);
  814. std::size_t n = 0;
  815. while(ret.first != ret.second){
  816. ++n;
  817. ret.first = next_node(ret.first);
  818. }
  819. return n;
  820. }
  821. //! <b>Requires</b>: "header" must be the header node of a tree.
  822. //! KeyNodePtrCompare is a function object that induces a strict weak
  823. //! ordering compatible with the strict weak ordering used to create the
  824. //! the tree. KeyNodePtrCompare can compare KeyType with tree's node_ptrs.
  825. //!
  826. //! <b>Effects</b>: Returns an a pair of node_ptr delimiting a range containing
  827. //! all elements that are equivalent to "key" according to "comp" or an
  828. //! empty range that indicates the position where those elements would be
  829. //! if there are no equivalent elements.
  830. //!
  831. //! <b>Complexity</b>: Logarithmic.
  832. //!
  833. //! <b>Throws</b>: If "comp" throws.
  834. template<class KeyType, class KeyNodePtrCompare>
  835. static std::pair<node_ptr, node_ptr> equal_range
  836. (const const_node_ptr & header, const KeyType &key, KeyNodePtrCompare comp)
  837. {
  838. return bounded_range(header, key, key, comp, true, true);
  839. }
  840. //! <b>Requires</b>: "header" must be the header node of a tree.
  841. //! KeyNodePtrCompare is a function object that induces a strict weak
  842. //! ordering compatible with the strict weak ordering used to create the
  843. //! the tree. KeyNodePtrCompare can compare KeyType with tree's node_ptrs.
  844. //!
  845. //! <b>Effects</b>: Returns an node_ptr to the first element that is
  846. //! not less than "key" according to "comp" or "header" if that element does
  847. //! not exist.
  848. //!
  849. //! <b>Complexity</b>: Logarithmic.
  850. //!
  851. //! <b>Throws</b>: If "comp" throws.
  852. template<class KeyType, class KeyNodePtrCompare>
  853. static node_ptr lower_bound
  854. (const const_node_ptr & header, const KeyType &key, KeyNodePtrCompare comp)
  855. {
  856. return lower_bound_loop(NodeTraits::get_parent(header), detail::uncast(header), key, comp);
  857. }
  858. //! <b>Requires</b>: "header" must be the header node of a tree.
  859. //! KeyNodePtrCompare is a function object that induces a strict weak
  860. //! ordering compatible with the strict weak ordering used to create the
  861. //! the tree. KeyNodePtrCompare can compare KeyType with tree's node_ptrs.
  862. //!
  863. //! <b>Effects</b>: Returns an node_ptr to the first element that is greater
  864. //! than "key" according to "comp" or "header" if that element does not exist.
  865. //!
  866. //! <b>Complexity</b>: Logarithmic.
  867. //!
  868. //! <b>Throws</b>: If "comp" throws.
  869. template<class KeyType, class KeyNodePtrCompare>
  870. static node_ptr upper_bound
  871. (const const_node_ptr & header, const KeyType &key, KeyNodePtrCompare comp)
  872. {
  873. return upper_bound_loop(NodeTraits::get_parent(header), detail::uncast(header), key, comp);
  874. }
  875. //! <b>Requires</b>: "header" must be the header node of a tree.
  876. //! "commit_data" must have been obtained from a previous call to
  877. //! "insert_unique_check". No objects should have been inserted or erased
  878. //! from the set between the "insert_unique_check" that filled "commit_data"
  879. //! and the call to "insert_commit".
  880. //!
  881. //!
  882. //! <b>Effects</b>: Inserts new_node in the set using the information obtained
  883. //! from the "commit_data" that a previous "insert_check" filled.
  884. //!
  885. //! <b>Complexity</b>: Constant time.
  886. //!
  887. //! <b>Throws</b>: Nothing.
  888. //!
  889. //! <b>Notes</b>: This function has only sense if a "insert_unique_check" has been
  890. //! previously executed to fill "commit_data". No value should be inserted or
  891. //! erased between the "insert_check" and "insert_commit" calls.
  892. static void insert_unique_commit
  893. (const node_ptr & header, const node_ptr & new_value, const insert_commit_data &commit_data)
  894. { return insert_commit(header, new_value, commit_data); }
  895. //! <b>Requires</b>: "header" must be the header node of a tree.
  896. //! KeyNodePtrCompare is a function object that induces a strict weak
  897. //! ordering compatible with the strict weak ordering used to create the
  898. //! the tree. NodePtrCompare compares KeyType with a node_ptr.
  899. //!
  900. //! <b>Effects</b>: Checks if there is an equivalent node to "key" in the
  901. //! tree according to "comp" and obtains the needed information to realize
  902. //! a constant-time node insertion if there is no equivalent node.
  903. //!
  904. //! <b>Returns</b>: If there is an equivalent value
  905. //! returns a pair containing a node_ptr to the already present node
  906. //! and false. If there is not equivalent key can be inserted returns true
  907. //! in the returned pair's boolean and fills "commit_data" that is meant to
  908. //! be used with the "insert_commit" function to achieve a constant-time
  909. //! insertion function.
  910. //!
  911. //! <b>Complexity</b>: Average complexity is at most logarithmic.
  912. //!
  913. //! <b>Throws</b>: If "comp" throws.
  914. //!
  915. //! <b>Notes</b>: This function is used to improve performance when constructing
  916. //! a node is expensive and the user does not want to have two equivalent nodes
  917. //! in the tree: if there is an equivalent value
  918. //! the constructed object must be discarded. Many times, the part of the
  919. //! node that is used to impose the order is much cheaper to construct
  920. //! than the node and this function offers the possibility to use that part
  921. //! to check if the insertion will be successful.
  922. //!
  923. //! If the check is successful, the user can construct the node and use
  924. //! "insert_commit" to insert the node in constant-time. This gives a total
  925. //! logarithmic complexity to the insertion: check(O(log(N)) + commit(O(1)).
  926. //!
  927. //! "commit_data" remains valid for a subsequent "insert_unique_commit" only
  928. //! if no more objects are inserted or erased from the set.
  929. template<class KeyType, class KeyNodePtrCompare>
  930. static std::pair<node_ptr, bool> insert_unique_check
  931. (const const_node_ptr & header, const KeyType &key
  932. ,KeyNodePtrCompare comp, insert_commit_data &commit_data
  933. #ifndef BOOST_INTRUSIVE_DOXYGEN_INVOKED
  934. , std::size_t *pdepth = 0
  935. #endif
  936. )
  937. {
  938. std::size_t depth = 0;
  939. node_ptr h(detail::uncast(header));
  940. node_ptr y(h);
  941. node_ptr x(NodeTraits::get_parent(y));
  942. node_ptr prev = node_ptr();
  943. //Find the upper bound, cache the previous value and if we should
  944. //store it in the left or right node
  945. bool left_child = true;
  946. while(x){
  947. ++depth;
  948. y = x;
  949. x = (left_child = comp(key, x)) ?
  950. NodeTraits::get_left(x) : (prev = y, NodeTraits::get_right(x));
  951. }
  952. if(pdepth) *pdepth = depth;
  953. //Since we've found the upper bound there is no other value with the same key if:
  954. // - There is no previous node
  955. // - The previous node is less than the key
  956. if(!prev || comp(prev, key)){
  957. commit_data.link_left = left_child;
  958. commit_data.node = y;
  959. return std::pair<node_ptr, bool>(node_ptr(), true);
  960. }
  961. //If the previous value was not less than key, it means that it's equal
  962. //(because we've checked the upper bound)
  963. else{
  964. return std::pair<node_ptr, bool>(prev, false);
  965. }
  966. }
  967. //! <b>Requires</b>: "header" must be the header node of a tree.
  968. //! KeyNodePtrCompare is a function object that induces a strict weak
  969. //! ordering compatible with the strict weak ordering used to create the
  970. //! the tree. NodePtrCompare compares KeyType with a node_ptr.
  971. //! "hint" is node from the "header"'s tree.
  972. //!
  973. //! <b>Effects</b>: Checks if there is an equivalent node to "key" in the
  974. //! tree according to "comp" using "hint" as a hint to where it should be
  975. //! inserted and obtains the needed information to realize
  976. //! a constant-time node insertion if there is no equivalent node.
  977. //! If "hint" is the upper_bound the function has constant time
  978. //! complexity (two comparisons in the worst case).
  979. //!
  980. //! <b>Returns</b>: If there is an equivalent value
  981. //! returns a pair containing a node_ptr to the already present node
  982. //! and false. If there is not equivalent key can be inserted returns true
  983. //! in the returned pair's boolean and fills "commit_data" that is meant to
  984. //! be used with the "insert_commit" function to achieve a constant-time
  985. //! insertion function.
  986. //!
  987. //! <b>Complexity</b>: Average complexity is at most logarithmic, but it is
  988. //! amortized constant time if new_node should be inserted immediately before "hint".
  989. //!
  990. //! <b>Throws</b>: If "comp" throws.
  991. //!
  992. //! <b>Notes</b>: This function is used to improve performance when constructing
  993. //! a node is expensive and the user does not want to have two equivalent nodes
  994. //! in the tree: if there is an equivalent value
  995. //! the constructed object must be discarded. Many times, the part of the
  996. //! node that is used to impose the order is much cheaper to construct
  997. //! than the node and this function offers the possibility to use that part
  998. //! to check if the insertion will be successful.
  999. //!
  1000. //! If the check is successful, the user can construct the node and use
  1001. //! "insert_commit" to insert the node in constant-time. This gives a total
  1002. //! logarithmic complexity to the insertion: check(O(log(N)) + commit(O(1)).
  1003. //!
  1004. //! "commit_data" remains valid for a subsequent "insert_unique_commit" only
  1005. //! if no more objects are inserted or erased from the set.
  1006. template<class KeyType, class KeyNodePtrCompare>
  1007. static std::pair<node_ptr, bool> insert_unique_check
  1008. (const const_node_ptr & header, const node_ptr &hint, const KeyType &key
  1009. ,KeyNodePtrCompare comp, insert_commit_data &commit_data
  1010. #ifndef BOOST_INTRUSIVE_DOXYGEN_INVOKED
  1011. , std::size_t *pdepth = 0
  1012. #endif
  1013. )
  1014. {
  1015. //hint must be bigger than the key
  1016. if(hint == header || comp(key, hint)){
  1017. node_ptr prev(hint);
  1018. //Previous value should be less than the key
  1019. if(hint == begin_node(header) || comp((prev = prev_node(hint)), key)){
  1020. commit_data.link_left = unique(header) || !NodeTraits::get_left(hint);
  1021. commit_data.node = commit_data.link_left ? hint : prev;
  1022. if(pdepth){
  1023. *pdepth = commit_data.node == header ? 0 : depth(commit_data.node) + 1;
  1024. }
  1025. return std::pair<node_ptr, bool>(node_ptr(), true);
  1026. }
  1027. }
  1028. //Hint was wrong, use hintless insertion
  1029. return insert_unique_check(header, key, comp, commit_data, pdepth);
  1030. }
  1031. //! <b>Requires</b>: "header" must be the header node of a tree.
  1032. //! NodePtrCompare is a function object that induces a strict weak
  1033. //! ordering compatible with the strict weak ordering used to create the
  1034. //! the tree. NodePtrCompare compares two node_ptrs. "hint" is node from
  1035. //! the "header"'s tree.
  1036. //!
  1037. //! <b>Effects</b>: Inserts new_node into the tree, using "hint" as a hint to
  1038. //! where it will be inserted. If "hint" is the upper_bound
  1039. //! the insertion takes constant time (two comparisons in the worst case).
  1040. //!
  1041. //! <b>Complexity</b>: Logarithmic in general, but it is amortized
  1042. //! constant time if new_node is inserted immediately before "hint".
  1043. //!
  1044. //! <b>Throws</b>: If "comp" throws.
  1045. template<class NodePtrCompare>
  1046. static node_ptr insert_equal
  1047. (const node_ptr & h, const node_ptr & hint, const node_ptr & new_node, NodePtrCompare comp
  1048. #ifndef BOOST_INTRUSIVE_DOXYGEN_INVOKED
  1049. , std::size_t *pdepth = 0
  1050. #endif
  1051. )
  1052. {
  1053. insert_commit_data commit_data;
  1054. insert_equal_check(h, hint, new_node, comp, commit_data, pdepth);
  1055. insert_commit(h, new_node, commit_data);
  1056. return new_node;
  1057. }
  1058. //! <b>Requires</b>: "h" must be the header node of a tree.
  1059. //! NodePtrCompare is a function object that induces a strict weak
  1060. //! ordering compatible with the strict weak ordering used to create the
  1061. //! the tree. NodePtrCompare compares two node_ptrs.
  1062. //!
  1063. //! <b>Effects</b>: Inserts new_node into the tree before the upper bound
  1064. //! according to "comp".
  1065. //!
  1066. //! <b>Complexity</b>: Average complexity for insert element is at
  1067. //! most logarithmic.
  1068. //!
  1069. //! <b>Throws</b>: If "comp" throws.
  1070. template<class NodePtrCompare>
  1071. static node_ptr insert_equal_upper_bound
  1072. (const node_ptr & h, const node_ptr & new_node, NodePtrCompare comp
  1073. #ifndef BOOST_INTRUSIVE_DOXYGEN_INVOKED
  1074. , std::size_t *pdepth = 0
  1075. #endif
  1076. )
  1077. {
  1078. insert_commit_data commit_data;
  1079. insert_equal_upper_bound_check(h, new_node, comp, commit_data, pdepth);
  1080. insert_commit(h, new_node, commit_data);
  1081. return new_node;
  1082. }
  1083. //! <b>Requires</b>: "h" must be the header node of a tree.
  1084. //! NodePtrCompare is a function object that induces a strict weak
  1085. //! ordering compatible with the strict weak ordering used to create the
  1086. //! the tree. NodePtrCompare compares two node_ptrs.
  1087. //!
  1088. //! <b>Effects</b>: Inserts new_node into the tree before the lower bound
  1089. //! according to "comp".
  1090. //!
  1091. //! <b>Complexity</b>: Average complexity for insert element is at
  1092. //! most logarithmic.
  1093. //!
  1094. //! <b>Throws</b>: If "comp" throws.
  1095. template<class NodePtrCompare>
  1096. static node_ptr insert_equal_lower_bound
  1097. (const node_ptr & h, const node_ptr & new_node, NodePtrCompare comp
  1098. #ifndef BOOST_INTRUSIVE_DOXYGEN_INVOKED
  1099. , std::size_t *pdepth = 0
  1100. #endif
  1101. )
  1102. {
  1103. insert_commit_data commit_data;
  1104. insert_equal_lower_bound_check(h, new_node, comp, commit_data, pdepth);
  1105. insert_commit(h, new_node, commit_data);
  1106. return new_node;
  1107. }
  1108. //! <b>Requires</b>: "header" must be the header node of a tree.
  1109. //! "pos" must be a valid iterator or header (end) node.
  1110. //! "pos" must be an iterator pointing to the successor to "new_node"
  1111. //! once inserted according to the order of already inserted nodes. This function does not
  1112. //! check "pos" and this precondition must be guaranteed by the caller.
  1113. //!
  1114. //! <b>Effects</b>: Inserts new_node into the tree before "pos".
  1115. //!
  1116. //! <b>Complexity</b>: Constant-time.
  1117. //!
  1118. //! <b>Throws</b>: Nothing.
  1119. //!
  1120. //! <b>Note</b>: If "pos" is not the successor of the newly inserted "new_node"
  1121. //! tree invariants might be broken.
  1122. static node_ptr insert_before
  1123. (const node_ptr & header, const node_ptr & pos, const node_ptr & new_node
  1124. #ifndef BOOST_INTRUSIVE_DOXYGEN_INVOKED
  1125. , std::size_t *pdepth = 0
  1126. #endif
  1127. )
  1128. {
  1129. insert_commit_data commit_data;
  1130. insert_before_check(header, pos, commit_data, pdepth);
  1131. insert_commit(header, new_node, commit_data);
  1132. return new_node;
  1133. }
  1134. //! <b>Requires</b>: "header" must be the header node of a tree.
  1135. //! "new_node" must be, according to the used ordering no less than the
  1136. //! greatest inserted key.
  1137. //!
  1138. //! <b>Effects</b>: Inserts new_node into the tree before "pos".
  1139. //!
  1140. //! <b>Complexity</b>: Constant-time.
  1141. //!
  1142. //! <b>Throws</b>: Nothing.
  1143. //!
  1144. //! <b>Note</b>: If "new_node" is less than the greatest inserted key
  1145. //! tree invariants are broken. This function is slightly faster than
  1146. //! using "insert_before".
  1147. static void push_back
  1148. (const node_ptr & header, const node_ptr & new_node
  1149. #ifndef BOOST_INTRUSIVE_DOXYGEN_INVOKED
  1150. , std::size_t *pdepth = 0
  1151. #endif
  1152. )
  1153. {
  1154. insert_commit_data commit_data;
  1155. push_back_check(header, commit_data, pdepth);
  1156. insert_commit(header, new_node, commit_data);
  1157. }
  1158. //! <b>Requires</b>: "header" must be the header node of a tree.
  1159. //! "new_node" must be, according to the used ordering, no greater than the
  1160. //! lowest inserted key.
  1161. //!
  1162. //! <b>Effects</b>: Inserts new_node into the tree before "pos".
  1163. //!
  1164. //! <b>Complexity</b>: Constant-time.
  1165. //!
  1166. //! <b>Throws</b>: Nothing.
  1167. //!
  1168. //! <b>Note</b>: If "new_node" is greater than the lowest inserted key
  1169. //! tree invariants are broken. This function is slightly faster than
  1170. //! using "insert_before".
  1171. static void push_front
  1172. (const node_ptr & header, const node_ptr & new_node
  1173. #ifndef BOOST_INTRUSIVE_DOXYGEN_INVOKED
  1174. , std::size_t *pdepth = 0
  1175. #endif
  1176. )
  1177. {
  1178. insert_commit_data commit_data;
  1179. push_front_check(header, commit_data, pdepth);
  1180. insert_commit(header, new_node, commit_data);
  1181. }
  1182. //! <b>Requires</b>: 'node' can't be a header node.
  1183. //!
  1184. //! <b>Effects</b>: Calculates the depth of a node: the depth of a
  1185. //! node is the length (number of edges) of the path from the root
  1186. //! to that node. (The root node is at depth 0.)
  1187. //!
  1188. //! <b>Complexity</b>: Logarithmic to the number of nodes in the tree.
  1189. //!
  1190. //! <b>Throws</b>: Nothing.
  1191. static std::size_t depth(const_node_ptr node)
  1192. {
  1193. std::size_t depth = 0;
  1194. node_ptr p_parent;
  1195. while(node != NodeTraits::get_parent(p_parent = NodeTraits::get_parent(node))){
  1196. ++depth;
  1197. node = p_parent;
  1198. }
  1199. return depth;
  1200. }
  1201. //! <b>Requires</b>: "cloner" must be a function
  1202. //! object taking a node_ptr and returning a new cloned node of it. "disposer" must
  1203. //! take a node_ptr and shouldn't throw.
  1204. //!
  1205. //! <b>Effects</b>: First empties target tree calling
  1206. //! <tt>void disposer::operator()(const node_ptr &)</tt> for every node of the tree
  1207. //! except the header.
  1208. //!
  1209. //! Then, duplicates the entire tree pointed by "source_header" cloning each
  1210. //! source node with <tt>node_ptr Cloner::operator()(const node_ptr &)</tt> to obtain
  1211. //! the nodes of the target tree. If "cloner" throws, the cloned target nodes
  1212. //! are disposed using <tt>void disposer(const node_ptr &)</tt>.
  1213. //!
  1214. //! <b>Complexity</b>: Linear to the number of element of the source tree plus the.
  1215. //! number of elements of tree target tree when calling this function.
  1216. //!
  1217. //! <b>Throws</b>: If cloner functor throws. If this happens target nodes are disposed.
  1218. template <class Cloner, class Disposer>
  1219. static void clone
  1220. (const const_node_ptr & source_header, const node_ptr & target_header, Cloner cloner, Disposer disposer)
  1221. {
  1222. if(!unique(target_header)){
  1223. clear_and_dispose(target_header, disposer);
  1224. }
  1225. node_ptr leftmost, rightmost;
  1226. node_ptr new_root = clone_subtree
  1227. (source_header, target_header, cloner, disposer, leftmost, rightmost);
  1228. //Now update header node
  1229. NodeTraits::set_parent(target_header, new_root);
  1230. NodeTraits::set_left (target_header, leftmost);
  1231. NodeTraits::set_right (target_header, rightmost);
  1232. }
  1233. //! <b>Requires</b>: header must be the header of a tree, z a node
  1234. //! of that tree and z != header.
  1235. //!
  1236. //! <b>Effects</b>: Erases node "z" from the tree with header "header".
  1237. //!
  1238. //! <b>Complexity</b>: Amortized constant time.
  1239. //!
  1240. //! <b>Throws</b>: Nothing.
  1241. static void erase(const node_ptr & header, const node_ptr & z)
  1242. {
  1243. data_for_rebalance ignored;
  1244. erase_impl(header, z, ignored);
  1245. }
  1246. //! <b>Requires</b>: node is a tree node but not the header.
  1247. //!
  1248. //! <b>Effects</b>: Unlinks the node and rebalances the tree.
  1249. //!
  1250. //! <b>Complexity</b>: Average complexity is constant time.
  1251. //!
  1252. //! <b>Throws</b>: Nothing.
  1253. static void unlink(const node_ptr & node)
  1254. {
  1255. node_ptr x = NodeTraits::get_parent(node);
  1256. if(x){
  1257. while(!is_header(x))
  1258. x = NodeTraits::get_parent(x);
  1259. erase(x, node);
  1260. }
  1261. }
  1262. //! <b>Requires</b>: header must be the header of a tree.
  1263. //!
  1264. //! <b>Effects</b>: Rebalances the tree.
  1265. //!
  1266. //! <b>Throws</b>: Nothing.
  1267. //!
  1268. //! <b>Complexity</b>: Linear.
  1269. static void rebalance(const node_ptr & header)
  1270. {
  1271. node_ptr root = NodeTraits::get_parent(header);
  1272. if(root){
  1273. rebalance_subtree(root);
  1274. }
  1275. }
  1276. //! <b>Requires</b>: old_root is a node of a tree. It shall not be null.
  1277. //!
  1278. //! <b>Effects</b>: Rebalances the subtree rooted at old_root.
  1279. //!
  1280. //! <b>Returns</b>: The new root of the subtree.
  1281. //!
  1282. //! <b>Throws</b>: Nothing.
  1283. //!
  1284. //! <b>Complexity</b>: Linear.
  1285. static node_ptr rebalance_subtree(const node_ptr & old_root)
  1286. {
  1287. //Taken from:
  1288. //"Tree rebalancing in optimal time and space"
  1289. //Quentin F. Stout and Bette L. Warren
  1290. //To avoid irregularities in the algorithm (old_root can be a
  1291. //left or right child or even the root of the tree) just put the
  1292. //root as the right child of its parent. Before doing this backup
  1293. //information to restore the original relationship after
  1294. //the algorithm is applied.
  1295. node_ptr super_root = NodeTraits::get_parent(old_root);
  1296. BOOST_INTRUSIVE_INVARIANT_ASSERT(super_root);
  1297. //Get root info
  1298. node_ptr super_root_right_backup = NodeTraits::get_right(super_root);
  1299. bool super_root_is_header = NodeTraits::get_parent(super_root) == old_root;
  1300. bool old_root_is_right = is_right_child(old_root);
  1301. NodeTraits::set_right(super_root, old_root);
  1302. std::size_t size;
  1303. subtree_to_vine(super_root, size);
  1304. vine_to_subtree(super_root, size);
  1305. node_ptr new_root = NodeTraits::get_right(super_root);
  1306. //Recover root
  1307. if(super_root_is_header){
  1308. NodeTraits::set_right(super_root, super_root_right_backup);
  1309. NodeTraits::set_parent(super_root, new_root);
  1310. }
  1311. else if(old_root_is_right){
  1312. NodeTraits::set_right(super_root, new_root);
  1313. }
  1314. else{
  1315. NodeTraits::set_right(super_root, super_root_right_backup);
  1316. NodeTraits::set_left(super_root, new_root);
  1317. }
  1318. return new_root;
  1319. }
  1320. protected:
  1321. //! <b>Requires</b>: node is a node of the tree but it's not the header.
  1322. //!
  1323. //! <b>Effects</b>: Returns the number of nodes of the subtree.
  1324. //!
  1325. //! <b>Complexity</b>: Linear time.
  1326. //!
  1327. //! <b>Throws</b>: Nothing.
  1328. static std::size_t subtree_size(const const_node_ptr & subtree)
  1329. {
  1330. std::size_t count = 0;
  1331. if (subtree){
  1332. node_ptr n = detail::uncast(subtree);
  1333. node_ptr m = NodeTraits::get_left(n);
  1334. while(m){
  1335. n = m;
  1336. m = NodeTraits::get_left(n);
  1337. }
  1338. while(1){
  1339. ++count;
  1340. node_ptr n_right(NodeTraits::get_right(n));
  1341. if(n_right){
  1342. n = n_right;
  1343. m = NodeTraits::get_left(n);
  1344. while(m){
  1345. n = m;
  1346. m = NodeTraits::get_left(n);
  1347. }
  1348. }
  1349. else {
  1350. do{
  1351. if (n == subtree){
  1352. return count;
  1353. }
  1354. m = n;
  1355. n = NodeTraits::get_parent(n);
  1356. }while(NodeTraits::get_left(n) != m);
  1357. }
  1358. }
  1359. }
  1360. return count;
  1361. }
  1362. //! <b>Requires</b>: p is a node of a tree.
  1363. //!
  1364. //! <b>Effects</b>: Returns true if p is a left child.
  1365. //!
  1366. //! <b>Complexity</b>: Constant.
  1367. //!
  1368. //! <b>Throws</b>: Nothing.
  1369. static bool is_left_child(const node_ptr & p)
  1370. { return NodeTraits::get_left(NodeTraits::get_parent(p)) == p; }
  1371. //! <b>Requires</b>: p is a node of a tree.
  1372. //!
  1373. //! <b>Effects</b>: Returns true if p is a right child.
  1374. //!
  1375. //! <b>Complexity</b>: Constant.
  1376. //!
  1377. //! <b>Throws</b>: Nothing.
  1378. static bool is_right_child(const node_ptr & p)
  1379. { return NodeTraits::get_right(NodeTraits::get_parent(p)) == p; }
  1380. template<class F>
  1381. static void erase(const node_ptr & header, const node_ptr & z, F z_and_successor_fixup, data_for_rebalance &info)
  1382. {
  1383. erase_impl(header, z, info);
  1384. if(info.y != z){
  1385. z_and_successor_fixup(z, info.y);
  1386. }
  1387. }
  1388. //Fix header and own's parent data when replacing x with own, providing own's old data with parent
  1389. static void replace_own_impl(const node_ptr & own, const node_ptr & x, const node_ptr & header, const node_ptr & own_parent, bool own_was_left)
  1390. {
  1391. if(NodeTraits::get_parent(header) == own)
  1392. NodeTraits::set_parent(header, x);
  1393. else if(own_was_left)
  1394. NodeTraits::set_left(own_parent, x);
  1395. else
  1396. NodeTraits::set_right(own_parent, x);
  1397. }
  1398. //Fix header and own's parent data when replacing x with own, supposing own
  1399. //links with its parent are still ok
  1400. static void replace_own(const node_ptr & own, const node_ptr & x, const node_ptr & header)
  1401. {
  1402. node_ptr own_parent(NodeTraits::get_parent(own));
  1403. bool own_is_left(NodeTraits::get_left(own_parent) == own);
  1404. replace_own_impl(own, x, header, own_parent, own_is_left);
  1405. }
  1406. // rotate parent p to left (no header and p's parent fixup)
  1407. static node_ptr rotate_left(const node_ptr & p)
  1408. {
  1409. node_ptr x(NodeTraits::get_right(p));
  1410. node_ptr x_left(NodeTraits::get_left(x));
  1411. NodeTraits::set_right(p, x_left);
  1412. if(x_left){
  1413. NodeTraits::set_parent(x_left, p);
  1414. }
  1415. NodeTraits::set_left(x, p);
  1416. NodeTraits::set_parent(p, x);
  1417. return x;
  1418. }
  1419. // rotate parent p to left (with header and p's parent fixup)
  1420. static void rotate_left(const node_ptr & p, const node_ptr & header)
  1421. {
  1422. bool p_was_left(is_left_child(p));
  1423. node_ptr p_old_parent(NodeTraits::get_parent(p));
  1424. node_ptr x(rotate_left(p));
  1425. NodeTraits::set_parent(x, p_old_parent);
  1426. replace_own_impl(p, x, header, p_old_parent, p_was_left);
  1427. }
  1428. // rotate parent p to right (no header and p's parent fixup)
  1429. static node_ptr rotate_right(const node_ptr & p)
  1430. {
  1431. node_ptr x(NodeTraits::get_left(p));
  1432. node_ptr x_right(NodeTraits::get_right(x));
  1433. NodeTraits::set_left(p, x_right);
  1434. if(x_right){
  1435. NodeTraits::set_parent(x_right, p);
  1436. }
  1437. NodeTraits::set_right(x, p);
  1438. NodeTraits::set_parent(p, x);
  1439. return x;
  1440. }
  1441. // rotate parent p to right (with header and p's parent fixup)
  1442. static void rotate_right(const node_ptr & p, const node_ptr & header)
  1443. {
  1444. bool p_was_left(is_left_child(p));
  1445. node_ptr p_old_parent(NodeTraits::get_parent(p));
  1446. node_ptr x(rotate_right(p));
  1447. NodeTraits::set_parent(x, p_old_parent);
  1448. replace_own_impl(p, x, header, p_old_parent, p_was_left);
  1449. }
  1450. static void insert_before_check
  1451. (const node_ptr &header, const node_ptr & pos
  1452. , insert_commit_data &commit_data
  1453. #ifndef BOOST_INTRUSIVE_DOXYGEN_INVOKED
  1454. , std::size_t *pdepth = 0
  1455. #endif
  1456. )
  1457. {
  1458. node_ptr prev(pos);
  1459. if(pos != NodeTraits::get_left(header))
  1460. prev = prev_node(pos);
  1461. bool link_left = unique(header) || !NodeTraits::get_left(pos);
  1462. commit_data.link_left = link_left;
  1463. commit_data.node = link_left ? pos : prev;
  1464. if(pdepth){
  1465. *pdepth = commit_data.node == header ? 0 : depth(commit_data.node) + 1;
  1466. }
  1467. }
  1468. static void push_back_check
  1469. (const node_ptr & header, insert_commit_data &commit_data
  1470. #ifndef BOOST_INTRUSIVE_DOXYGEN_INVOKED
  1471. , std::size_t *pdepth = 0
  1472. #endif
  1473. )
  1474. {
  1475. node_ptr prev(NodeTraits::get_right(header));
  1476. if(pdepth){
  1477. *pdepth = prev == header ? 0 : depth(prev) + 1;
  1478. }
  1479. commit_data.link_left = false;
  1480. commit_data.node = prev;
  1481. }
  1482. static void push_front_check
  1483. (const node_ptr & header, insert_commit_data &commit_data
  1484. #ifndef BOOST_INTRUSIVE_DOXYGEN_INVOKED
  1485. , std::size_t *pdepth = 0
  1486. #endif
  1487. )
  1488. {
  1489. node_ptr pos(NodeTraits::get_left(header));
  1490. if(pdepth){
  1491. *pdepth = pos == header ? 0 : depth(pos) + 1;
  1492. }
  1493. commit_data.link_left = true;
  1494. commit_data.node = pos;
  1495. }
  1496. template<class NodePtrCompare>
  1497. static void insert_equal_check
  1498. (const node_ptr &header, const node_ptr & hint, const node_ptr & new_node, NodePtrCompare comp
  1499. , insert_commit_data &commit_data
  1500. /// @cond
  1501. , std::size_t *pdepth = 0
  1502. /// @endcond
  1503. )
  1504. {
  1505. if(hint == header || !comp(hint, new_node)){
  1506. node_ptr prev(hint);
  1507. if(hint == NodeTraits::get_left(header) ||
  1508. !comp(new_node, (prev = prev_node(hint)))){
  1509. bool link_left = unique(header) || !NodeTraits::get_left(hint);
  1510. commit_data.link_left = link_left;
  1511. commit_data.node = link_left ? hint : prev;
  1512. if(pdepth){
  1513. *pdepth = commit_data.node == header ? 0 : depth(commit_data.node) + 1;
  1514. }
  1515. }
  1516. else{
  1517. insert_equal_upper_bound_check(header, new_node, comp, commit_data, pdepth);
  1518. }
  1519. }
  1520. else{
  1521. insert_equal_lower_bound_check(header, new_node, comp, commit_data, pdepth);
  1522. }
  1523. }
  1524. template<class NodePtrCompare>
  1525. static void insert_equal_upper_bound_check
  1526. (const node_ptr & h, const node_ptr & new_node, NodePtrCompare comp, insert_commit_data & commit_data, std::size_t *pdepth = 0)
  1527. { insert_equal_check_impl(true, h, new_node, comp, commit_data, pdepth); }
  1528. template<class NodePtrCompare>
  1529. static void insert_equal_lower_bound_check
  1530. (const node_ptr & h, const node_ptr & new_node, NodePtrCompare comp, insert_commit_data & commit_data, std::size_t *pdepth = 0)
  1531. { insert_equal_check_impl(false, h, new_node, comp, commit_data, pdepth); }
  1532. static void insert_commit
  1533. (const node_ptr & header, const node_ptr & new_node, const insert_commit_data &commit_data)
  1534. {
  1535. //Check if commit_data has not been initialized by a insert_unique_check call.
  1536. BOOST_INTRUSIVE_INVARIANT_ASSERT(commit_data.node != node_ptr());
  1537. node_ptr parent_node(commit_data.node);
  1538. if(parent_node == header){
  1539. NodeTraits::set_parent(header, new_node);
  1540. NodeTraits::set_right(header, new_node);
  1541. NodeTraits::set_left(header, new_node);
  1542. }
  1543. else if(commit_data.link_left){
  1544. NodeTraits::set_left(parent_node, new_node);
  1545. if(parent_node == NodeTraits::get_left(header))
  1546. NodeTraits::set_left(header, new_node);
  1547. }
  1548. else{
  1549. NodeTraits::set_right(parent_node, new_node);
  1550. if(parent_node == NodeTraits::get_right(header))
  1551. NodeTraits::set_right(header, new_node);
  1552. }
  1553. NodeTraits::set_parent(new_node, parent_node);
  1554. NodeTraits::set_right(new_node, node_ptr());
  1555. NodeTraits::set_left(new_node, node_ptr());
  1556. }
  1557. private:
  1558. static void subtree_to_vine(node_ptr vine_tail, std::size_t &size)
  1559. {
  1560. //Inspired by LibAVL:
  1561. //It uses a clever optimization for trees with parent pointers.
  1562. //No parent pointer is updated when transforming a tree to a vine as
  1563. //most of them will be overriten during compression rotations.
  1564. //A final pass must be made after the rebalancing to updated those
  1565. //pointers not updated by tree_to_vine + compression calls
  1566. std::size_t len = 0;
  1567. node_ptr remainder = NodeTraits::get_right(vine_tail);
  1568. while(remainder){
  1569. node_ptr tempptr = NodeTraits::get_left(remainder);
  1570. if(!tempptr){ //move vine-tail down one
  1571. vine_tail = remainder;
  1572. remainder = NodeTraits::get_right(remainder);
  1573. ++len;
  1574. }
  1575. else{ //rotate
  1576. NodeTraits::set_left(remainder, NodeTraits::get_right(tempptr));
  1577. NodeTraits::set_right(tempptr, remainder);
  1578. remainder = tempptr;
  1579. NodeTraits::set_right(vine_tail, tempptr);
  1580. }
  1581. }
  1582. size = len;
  1583. }
  1584. static void compress_subtree(node_ptr scanner, std::size_t count)
  1585. {
  1586. while(count--){ //compress "count" spine nodes in the tree with pseudo-root scanner
  1587. node_ptr child = NodeTraits::get_right(scanner);
  1588. node_ptr child_right = NodeTraits::get_right(child);
  1589. NodeTraits::set_right(scanner, child_right);
  1590. //Avoid setting the parent of child_right
  1591. scanner = child_right;
  1592. node_ptr scanner_left = NodeTraits::get_left(scanner);
  1593. NodeTraits::set_right(child, scanner_left);
  1594. if(scanner_left)
  1595. NodeTraits::set_parent(scanner_left, child);
  1596. NodeTraits::set_left(scanner, child);
  1597. NodeTraits::set_parent(child, scanner);
  1598. }
  1599. }
  1600. static void vine_to_subtree(const node_ptr & super_root, std::size_t count)
  1601. {
  1602. std::size_t leaf_nodes = count + 1 - ((std::size_t) 1 << detail::floor_log2(count + 1));
  1603. compress_subtree(super_root, leaf_nodes); //create deepest leaves
  1604. std::size_t vine_nodes = count - leaf_nodes;
  1605. while(vine_nodes > 1){
  1606. vine_nodes /= 2;
  1607. compress_subtree(super_root, vine_nodes);
  1608. }
  1609. //Update parents of nodes still in the in the original vine line
  1610. //as those have not been updated by subtree_to_vine or compress_subtree
  1611. for ( node_ptr q = super_root, p = NodeTraits::get_right(super_root)
  1612. ; p
  1613. ; q = p, p = NodeTraits::get_right(p)){
  1614. NodeTraits::set_parent(p, q);
  1615. }
  1616. }
  1617. //! <b>Requires</b>: "n" must be a node inserted in a tree.
  1618. //!
  1619. //! <b>Effects</b>: Returns a pointer to the header node of the tree.
  1620. //!
  1621. //! <b>Complexity</b>: Logarithmic.
  1622. //!
  1623. //! <b>Throws</b>: Nothing.
  1624. static node_ptr get_root(const node_ptr & node)
  1625. {
  1626. BOOST_INTRUSIVE_INVARIANT_ASSERT((!inited(node)));
  1627. node_ptr x = NodeTraits::get_parent(node);
  1628. if(x){
  1629. while(!is_header(x)){
  1630. x = NodeTraits::get_parent(x);
  1631. }
  1632. return x;
  1633. }
  1634. else{
  1635. return node;
  1636. }
  1637. }
  1638. template <class Cloner, class Disposer>
  1639. static node_ptr clone_subtree
  1640. (const const_node_ptr &source_parent, const node_ptr &target_parent
  1641. , Cloner cloner, Disposer disposer
  1642. , node_ptr &leftmost_out, node_ptr &rightmost_out
  1643. )
  1644. {
  1645. node_ptr target_sub_root = target_parent;
  1646. node_ptr source_root = NodeTraits::get_parent(source_parent);
  1647. if(!source_root){
  1648. leftmost_out = rightmost_out = source_root;
  1649. }
  1650. else{
  1651. //We'll calculate leftmost and rightmost nodes while iterating
  1652. node_ptr current = source_root;
  1653. node_ptr insertion_point = target_sub_root = cloner(current);
  1654. //We'll calculate leftmost and rightmost nodes while iterating
  1655. node_ptr leftmost = target_sub_root;
  1656. node_ptr rightmost = target_sub_root;
  1657. //First set the subroot
  1658. NodeTraits::set_left(target_sub_root, node_ptr());
  1659. NodeTraits::set_right(target_sub_root, node_ptr());
  1660. NodeTraits::set_parent(target_sub_root, target_parent);
  1661. dispose_subtree_disposer<Disposer> rollback(disposer, target_sub_root);
  1662. while(true) {
  1663. //First clone left nodes
  1664. if( NodeTraits::get_left(current) &&
  1665. !NodeTraits::get_left(insertion_point)) {
  1666. current = NodeTraits::get_left(current);
  1667. node_ptr temp = insertion_point;
  1668. //Clone and mark as leaf
  1669. insertion_point = cloner(current);
  1670. NodeTraits::set_left (insertion_point, node_ptr());
  1671. NodeTraits::set_right (insertion_point, node_ptr());
  1672. //Insert left
  1673. NodeTraits::set_parent(insertion_point, temp);
  1674. NodeTraits::set_left (temp, insertion_point);
  1675. //Update leftmost
  1676. if(rightmost == target_sub_root)
  1677. leftmost = insertion_point;
  1678. }
  1679. //Then clone right nodes
  1680. else if( NodeTraits::get_right(current) &&
  1681. !NodeTraits::get_right(insertion_point)){
  1682. current = NodeTraits::get_right(current);
  1683. node_ptr temp = insertion_point;
  1684. //Clone and mark as leaf
  1685. insertion_point = cloner(current);
  1686. NodeTraits::set_left (insertion_point, node_ptr());
  1687. NodeTraits::set_right (insertion_point, node_ptr());
  1688. //Insert right
  1689. NodeTraits::set_parent(insertion_point, temp);
  1690. NodeTraits::set_right (temp, insertion_point);
  1691. //Update rightmost
  1692. rightmost = insertion_point;
  1693. }
  1694. //If not, go up
  1695. else if(current == source_root){
  1696. break;
  1697. }
  1698. else{
  1699. //Branch completed, go up searching more nodes to clone
  1700. current = NodeTraits::get_parent(current);
  1701. insertion_point = NodeTraits::get_parent(insertion_point);
  1702. }
  1703. }
  1704. rollback.release();
  1705. leftmost_out = leftmost;
  1706. rightmost_out = rightmost;
  1707. }
  1708. return target_sub_root;
  1709. }
  1710. template<class Disposer>
  1711. static void dispose_subtree(node_ptr x, Disposer disposer)
  1712. {
  1713. while (x){
  1714. node_ptr save(NodeTraits::get_left(x));
  1715. if (save) {
  1716. // Right rotation
  1717. NodeTraits::set_left(x, NodeTraits::get_right(save));
  1718. NodeTraits::set_right(save, x);
  1719. }
  1720. else {
  1721. save = NodeTraits::get_right(x);
  1722. init(x);
  1723. disposer(x);
  1724. }
  1725. x = save;
  1726. }
  1727. }
  1728. template<class KeyType, class KeyNodePtrCompare>
  1729. static node_ptr lower_bound_loop
  1730. (node_ptr x, node_ptr y, const KeyType &key, KeyNodePtrCompare comp)
  1731. {
  1732. while(x){
  1733. if(comp(x, key)){
  1734. x = NodeTraits::get_right(x);
  1735. }
  1736. else{
  1737. y = x;
  1738. x = NodeTraits::get_left(x);
  1739. }
  1740. }
  1741. return y;
  1742. }
  1743. template<class KeyType, class KeyNodePtrCompare>
  1744. static node_ptr upper_bound_loop
  1745. (node_ptr x, node_ptr y, const KeyType &key, KeyNodePtrCompare comp)
  1746. {
  1747. while(x){
  1748. if(comp(key, x)){
  1749. y = x;
  1750. x = NodeTraits::get_left(x);
  1751. }
  1752. else{
  1753. x = NodeTraits::get_right(x);
  1754. }
  1755. }
  1756. return y;
  1757. }
  1758. template<class NodePtrCompare>
  1759. static void insert_equal_check_impl
  1760. (bool upper, const node_ptr & h, const node_ptr & new_node, NodePtrCompare comp, insert_commit_data & commit_data, std::size_t *pdepth = 0)
  1761. {
  1762. std::size_t depth = 0;
  1763. node_ptr y(h);
  1764. node_ptr x(NodeTraits::get_parent(y));
  1765. bool link_left;
  1766. if(upper){
  1767. while(x){
  1768. ++depth;
  1769. y = x;
  1770. x = comp(new_node, x) ?
  1771. NodeTraits::get_left(x) : NodeTraits::get_right(x);
  1772. }
  1773. link_left = (y == h) || comp(new_node, y);
  1774. }
  1775. else{
  1776. while(x){
  1777. ++depth;
  1778. y = x;
  1779. x = !comp(x, new_node) ?
  1780. NodeTraits::get_left(x) : NodeTraits::get_right(x);
  1781. }
  1782. link_left = (y == h) || !comp(y, new_node);
  1783. }
  1784. commit_data.link_left = link_left;
  1785. commit_data.node = y;
  1786. if(pdepth) *pdepth = depth;
  1787. }
  1788. static void erase_impl(const node_ptr & header, const node_ptr & z, data_for_rebalance &info)
  1789. {
  1790. node_ptr y(z);
  1791. node_ptr x;
  1792. node_ptr x_parent = node_ptr();
  1793. node_ptr z_left(NodeTraits::get_left(z));
  1794. node_ptr z_right(NodeTraits::get_right(z));
  1795. if(!z_left){
  1796. x = z_right; // x might be null.
  1797. }
  1798. else if(!z_right){ // z has exactly one non-null child. y == z.
  1799. x = z_left; // x is not null.
  1800. }
  1801. else{
  1802. // find z's successor
  1803. y = bstree_algorithms::minimum (z_right);
  1804. x = NodeTraits::get_right(y); // x might be null.
  1805. }
  1806. if(y != z){
  1807. // relink y in place of z. y is z's successor
  1808. NodeTraits::set_parent(NodeTraits::get_left(z), y);
  1809. NodeTraits::set_left(y, NodeTraits::get_left(z));
  1810. if(y != NodeTraits::get_right(z)){
  1811. x_parent = NodeTraits::get_parent(y);
  1812. if(x)
  1813. NodeTraits::set_parent(x, x_parent);
  1814. NodeTraits::set_left(x_parent, x); // y must be a child of left_
  1815. NodeTraits::set_right(y, NodeTraits::get_right(z));
  1816. NodeTraits::set_parent(NodeTraits::get_right(z), y);
  1817. }
  1818. else
  1819. x_parent = y;
  1820. bstree_algorithms::replace_own (z, y, header);
  1821. NodeTraits::set_parent(y, NodeTraits::get_parent(z));
  1822. }
  1823. else { // y == z --> z has only one child, or void
  1824. x_parent = NodeTraits::get_parent(z);
  1825. if(x)
  1826. NodeTraits::set_parent(x, x_parent);
  1827. bstree_algorithms::replace_own (z, x, header);
  1828. if(NodeTraits::get_left(header) == z){
  1829. NodeTraits::set_left(header, !NodeTraits::get_right(z) ? // z->get_left() must be null also
  1830. NodeTraits::get_parent(z) : // makes leftmost == header if z == root
  1831. bstree_algorithms::minimum (x));
  1832. }
  1833. if(NodeTraits::get_right(header) == z){
  1834. NodeTraits::set_right(header, !NodeTraits::get_left(z) ? // z->get_right() must be null also
  1835. NodeTraits::get_parent(z) : // makes rightmost == header if z == root
  1836. bstree_algorithms::maximum(x));
  1837. }
  1838. }
  1839. info.x = x;
  1840. info.x_parent = x_parent;
  1841. info.y = y;
  1842. }
  1843. };
  1844. /// @cond
  1845. template<class NodeTraits>
  1846. struct get_algo<BsTreeAlgorithms, NodeTraits>
  1847. {
  1848. typedef bstree_algorithms<NodeTraits> type;
  1849. };
  1850. /// @endcond
  1851. } //namespace intrusive
  1852. } //namespace boost
  1853. #include <boost/intrusive/detail/config_end.hpp>
  1854. #endif //BOOST_INTRUSIVE_BSTREE_ALGORITHMS_HPP