rbtree.h 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697
  1. // Copyright (C) 2010 Internet Systems Consortium, Inc. ("ISC")
  2. //
  3. // Permission to use, copy, modify, and/or distribute this software for any
  4. // purpose with or without fee is hereby granted, provided that the above
  5. // copyright notice and this permission notice appear in all copies.
  6. //
  7. // THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
  8. // REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
  9. // AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
  10. // INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
  11. // LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
  12. // OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
  13. // PERFORMANCE OF THIS SOFTWARE.
  14. #ifndef _RBTREE_H
  15. #define _RBTREE_H 1
  16. //! \file datasrc/rbtree.h
  17. ///
  18. /// \note The purpose of the RBTree is to provide a generic map with
  19. /// domain names as the key that can be used by various BIND 10 modules or
  20. /// even by other applications. However, because of some unresolved design
  21. /// issue, the design and interface are not fixed, and RBTree isn't ready to
  22. /// be used as a base data structure by other modules.
  23. #include <dns/name.h>
  24. #include <boost/utility.hpp>
  25. #include <boost/shared_ptr.hpp>
  26. #include <exception>
  27. #include <ostream>
  28. #include <algorithm>
  29. namespace isc {
  30. namespace datasrc {
  31. namespace helper {
  32. /// Helper function to remove the base domain from super domain
  33. ///
  34. /// the precondition of this function is the super_name contains the
  35. /// sub_name so \code Name a("a.b.c"); Name b("b.c");
  36. /// Name c = a - b; \\c will be "a" \endcode
  37. ///
  38. /// \note function in this namespace is not intended to be used outside.
  39. inline isc::dns::Name
  40. operator-(const isc::dns::Name& super_name, const isc::dns::Name& sub_name) {
  41. return (super_name.split(0, super_name.getLabelCount() -
  42. sub_name.getLabelCount()));
  43. }
  44. }
  45. template <typename T>
  46. class RBTree;
  47. /// \brief \c RBNode use by RBTree to store any data related to one domain name
  48. /// It has two roles, the first one is as one node in the \c RBTree,
  49. /// the second one is to store the data related to one domain name and maintain
  50. /// the domain name hierarchy struct in one domain name space.
  51. /// As for the first role, it has left, right, parent and color members
  52. /// which is used to keep the balance of the \c RBTree.
  53. /// As for the second role, \c RBNode use down pointer to refer to all its sub
  54. /// domains, so the name of current node always relative to the up node. since
  55. /// we only has down pointer without up pointer, so we can only walk down from
  56. /// top domain to sub domain.
  57. /// One special kind of node is non-terminal node
  58. /// which has subdomains with RRset but itself doesn't have any RRsets.
  59. ///
  60. /// \note \c RBNode basically used internally by RBTree, it is meaningless to
  61. /// inherited from it or create it without \c RBTree.
  62. template <typename T>
  63. class RBNode : public boost::noncopyable {
  64. public:
  65. /// only \c RBTree can create and destroy \c RBNode
  66. friend class RBTree<T>;
  67. typedef boost::shared_ptr<T> NodeDataPtr;
  68. /// \name Deonstructor
  69. /// \note it's seems a little strange that constructor is private
  70. /// but deconstructor left public, the reason is for some smart pointer
  71. /// like std::auto_ptr, they needs to delete RBNode in sometimes, but
  72. /// \code delete *pointer_to_node \codeend shouldn't be called directly
  73. //@{
  74. ~RBNode();
  75. //@}
  76. /// \name Test functions
  77. //@{
  78. /// \brief return the name of current node, it's relative to its top node
  79. ///
  80. /// To get the absolute name of one node, the node path from the top node
  81. /// to current node has to be recorded
  82. const isc::dns::Name& getName() const { return (name_); }
  83. /// \brief return the data store in this node
  84. /// \note, since the data is managed by RBNode, developer should not
  85. /// free the pointer
  86. NodeDataPtr& getData() { return (data_); }
  87. /// \brief return the data stored in this node, read-only version
  88. const NodeDataPtr& getData() const { return (data_); }
  89. /// \brief return whether the node has related data
  90. /// \note it's meaningless has empty \c RBNode in one RBTree, the only
  91. /// exception is for non-terminal node which has sub domain nodes who
  92. /// has data(rrset)
  93. bool isEmpty() const { return (data_.get() == NULL); }
  94. //@}
  95. /// \name Modify functions
  96. //@{
  97. /// \breif set the data stored in the node
  98. void setData(const NodeDataPtr& data) { data_ = data; }
  99. //@}
  100. private:
  101. /// \brief Define rbnode color
  102. enum RBNodeColor {BLACK, RED};
  103. /// \name Constructors
  104. /// \note \c Single RBNode is meaningless without living inside one \c RBTree
  105. /// the creation and destroy of one \c RBNode is handle by host \c RBTree, so
  106. /// the constructors and destructor of \c RBNode is left private
  107. //@{
  108. /// \brief Default constructor.
  109. ///
  110. /// This constructor is provided specifically for generating a special
  111. /// "null" node, and is intended be used only internally.
  112. RBNode();
  113. /// \brief Constructor from the node name.
  114. ///
  115. /// \param name The domain name corresponding to the node.
  116. RBNode(const isc::dns::Name& name);
  117. //@}
  118. /// This is a factory class method of a special singleton null node.
  119. static RBNode<T>* NULL_NODE() {
  120. static RBNode<T> null_node;
  121. return (&null_node);
  122. }
  123. /// data to maintain the rbtree balance
  124. RBNode<T>* parent_;
  125. RBNode<T>* left_;
  126. RBNode<T>* right_;
  127. RBNodeColor color_;
  128. isc::dns::Name name_;
  129. NodeDataPtr data_;
  130. /// the down pointer points to the root node of sub domains of current
  131. /// domain
  132. /// \par Adding down pointer to \c RBNode is for two purpose:
  133. /// \li Accelerate the search process, with sub domain tree, it split the
  134. /// big flat tree into several hierarchy trees
  135. /// \li It save memory useage, so same label won't be saved several times
  136. RBNode<T>* down_;
  137. };
  138. // typically each node should has a name associate with it
  139. // this construction is only used to create \c NULLNODE
  140. template <typename T>
  141. RBNode<T>::RBNode() :
  142. parent_(this),
  143. left_(this),
  144. right_(this),
  145. color_(BLACK),
  146. // dummy name, the value doesn't matter:
  147. name_(isc::dns::Name::ROOT_NAME()),
  148. down_(this)
  149. {
  150. }
  151. template <typename T>
  152. RBNode<T>::RBNode(const isc::dns::Name& name) :
  153. parent_(NULL_NODE()),
  154. left_(NULL_NODE()),
  155. right_(NULL_NODE()),
  156. color_(RED),
  157. name_(name),
  158. down_(NULL_NODE())
  159. {
  160. }
  161. template <typename T>
  162. RBNode<T>::~RBNode() {
  163. }
  164. /// \brief \c RBTree class represents all the domains with the same suffix,
  165. /// so it can be used to store the domains in one zone.
  166. ///
  167. /// \c RBTree is a generic red black tree, and contains all the nodes with
  168. /// the same suffix, since each name may have sub domain names
  169. /// so \c RBTree is a recursive data structure namely tree in tree.
  170. /// So for one zone, several RBTrees may be involved. But from outside, the sub
  171. /// tree is opaque for end users.
  172. ///
  173. /// \c RBTree split the domain space into hierarchy red black trees, nodes in one
  174. /// tree has the same base name. The benefit of this struct is that:
  175. /// - enhance the query performace compared with one big flat red black tree
  176. /// - decrase the memory footprint to save common labels only once.
  177. /*
  178. /// \verbatim
  179. /// with the following names:
  180. /// a x.d.e.f o.w.y.d.e.f
  181. /// b z.d.e.f p.w.y.d.e.f
  182. /// c g.h q.w.y.d.e.f
  183. /// the tree will looks like:
  184. /// b
  185. /// / \
  186. /// a d.e.f
  187. /// /|\
  188. /// c | g.h
  189. /// |
  190. /// w.y
  191. /// /|\
  192. /// x | z
  193. /// |
  194. /// p
  195. /// / \
  196. /// o q
  197. /// \endverbatim
  198. /// \note open problems:
  199. /// - current find funciton only return non-empty nodes, so there is no difference
  200. /// between find one not exist name with empty non-terminal nodes, but in DNS query
  201. /// logic, they are different
  202. /// \todo
  203. /// - add remove interface
  204. /// - add iterator to iterate the whole rbtree while may needed by axfr
  205. /// - since \c RBNode only has down pointer without up pointer, the node path during finding
  206. /// should be recorded for later use
  207. */
  208. template <typename T>
  209. class RBTree : public boost::noncopyable {
  210. friend class RBNode<T>;
  211. public:
  212. /// \brief The return value for the \c find() insert() and erase() method
  213. enum Result {
  214. SUCCEED, //insert or erase succeed
  215. EXACTMATCH, //find the target name
  216. PARTIALMATCH, //find part of target name
  217. NOTFOUND, // for find function means no related name found
  218. // for erase function means erase not exist name
  219. ALREADYEXIST, //for insert operation, the name to insert already exist
  220. };
  221. /// \name Constructor and Destructor
  222. //@{
  223. RBTree();
  224. /// \b Note: RBTree is not intended to be inherited so the destructor
  225. /// is not virtual
  226. ~RBTree();
  227. //@}
  228. /// \name Inquery methods
  229. //@{
  230. /// \brief Find the node with the name
  231. /// \param name Target to be found
  232. /// \param node Point to the node when the return vaule is \c not
  233. /// NOTFOUND, if the return value is NOTFOUND, the value of node is
  234. /// \c unknown
  235. Result find(const isc::dns::Name& name, RBNode<T>** node) const;
  236. Result find(const isc::dns::Name& name, const RBNode<T>** node) const;
  237. /// \brief Get the total node count in the tree
  238. /// the node count including the node created common suffix node,
  239. /// this function will only be used for debuging
  240. int getNodeCount() const { return (node_count_);}
  241. //@}
  242. /// \name Debug function
  243. //@{
  244. /// \brief print the nodes in the trees
  245. void dumpTree(std::ostream& os, unsigned int depth = 0) const;
  246. //@}
  247. /// \name Modify function
  248. //@{
  249. /// \brief Insert the domain name into the tree
  250. /// \param name The name to be inserted into the tree
  251. /// \param inserted_node If no node with the name in the tree,
  252. /// new \c RBNode will be created, otherwise nothing will be done.
  253. /// Anyway the pointer point to the node with the name will be assigned to
  254. /// inserted_node
  255. /// \return
  256. // - SUCCEED means no node exists in the tree with the name before insert
  257. /// - ALREADYEXIST means already has the node with the given name
  258. //
  259. /// \node To modify the data related with one name but not sure the name has
  260. /// inserted or not, it is better to call \code insert \endcode,instead of
  261. /// \code find() \endcode, in case the name isn't exist and needs to insert again
  262. Result insert(const isc::dns::Name& name, RBNode<T>** inserted_node);
  263. //@}
  264. /// \brief Swaps two tree's contents.
  265. ///
  266. /// This acts the same as many std::*.swap functions, exchanges the
  267. /// contents. This doesn't throw anything.
  268. void swap(RBTree<T>& other) {
  269. std::swap(root_, other.root_);
  270. std::swap(NULLNODE, other.NULLNODE);
  271. std::swap(node_count_, other.node_count_);
  272. }
  273. private:
  274. /// \name RBTree balance functions
  275. //@{
  276. void insertRebalance(RBNode<T>** root, RBNode<T>* node);
  277. RBNode<T>* rightRotate(RBNode<T>** root, RBNode<T>* node);
  278. RBNode<T>* leftRotate(RBNode<T>** root, RBNode<T>* node);
  279. //@}
  280. /// \name Helper functions
  281. //@{
  282. /// \brief delete tree whose root is equal to node
  283. void deleteHelper(RBNode<T> *node);
  284. /// \brief find the node with name
  285. /// \param name is the target, up will points to the base domain of
  286. /// the tree which name resides, node will point to the target node
  287. /// if we has exact same name or partical name in current tree.
  288. /// so for example, in zone a, we has
  289. /// b.a, c.b.a and d.b.a search c.b.a, up will points to b.a.
  290. /// and node will points to c.b.a
  291. /// \note parameter up now is not used by any funciton, but we are gonna
  292. /// need it soon to implement function like remove
  293. Result findHelper(const isc::dns::Name& name, const RBNode<T>** up,
  294. RBNode<T>** node) const;
  295. void dumpTreeHelper(std::ostream& os, const RBNode<T>* node,
  296. unsigned int depth) const;
  297. /// for indent purpose, add certian mount empty charachter to output stream
  298. /// according to the depth. This is a helper function which is only used when
  299. /// dump tree
  300. static void indent(std::ostream& os, unsigned int depth);
  301. /// Split one node into two nodes, keep the old node and create one new
  302. /// node, old node will hold the base name, new node will be the down node
  303. /// of old node, new node will hold the sub_name, the data
  304. /// of old node will be move into new node, and old node became non-terminal
  305. void nodeFission(RBNode<T>& node, const isc::dns::Name& sub_name);
  306. //@}
  307. RBNode<T>* root_;
  308. RBNode<T>* NULLNODE;
  309. /// the node count of current tree
  310. unsigned int node_count_;
  311. };
  312. template <typename T>
  313. RBTree<T>::RBTree() {
  314. NULLNODE = RBNode<T>::NULL_NODE();
  315. root_ = NULLNODE;
  316. node_count_ = 0;
  317. }
  318. template <typename T>
  319. RBTree<T>::~RBTree() {
  320. deleteHelper(root_);
  321. assert(node_count_ == 0);
  322. }
  323. template <typename T>
  324. void RBTree<T> ::deleteHelper(RBNode<T> *root) {
  325. if (root == NULLNODE) {
  326. return;
  327. }
  328. RBNode<T> *node = root;
  329. while (root->left_ != NULLNODE || root->right_ != NULLNODE) {
  330. while (node->left_ != NULLNODE || node->right_ != NULLNODE) {
  331. node = (node->left_ != NULLNODE) ? node->left_ : node->right_;
  332. }
  333. RBNode<T> *parent = node->parent_;
  334. if (parent->left_ == node) {
  335. parent->left_ = NULLNODE;
  336. } else {
  337. parent->right_ = NULLNODE;
  338. }
  339. deleteHelper(node->down_);
  340. delete node;
  341. --node_count_;
  342. node = parent;
  343. }
  344. deleteHelper(root->down_);
  345. delete root;
  346. --node_count_;
  347. }
  348. template <typename T>
  349. typename RBTree<T>::Result
  350. RBTree<T>::find(const isc::dns::Name& name, RBNode<T>** node) const {
  351. const RBNode<T>* up_node = NULLNODE;
  352. return (findHelper(name, &up_node, node));
  353. }
  354. template <typename T>
  355. typename RBTree<T>::Result
  356. RBTree<T>::find(const isc::dns::Name& name, const RBNode<T>** node) const {
  357. const RBNode<T>* up_node;
  358. RBNode<T>* target_node;
  359. const typename RBTree<T>::Result ret =
  360. findHelper(name, &up_node, &target_node);
  361. if (ret != NOTFOUND) {
  362. *node = target_node;
  363. }
  364. return (ret);
  365. }
  366. template <typename T>
  367. typename RBTree<T>::Result
  368. RBTree<T>::findHelper(const isc::dns::Name& target_name, const RBNode<T>** up_node,
  369. RBNode<T>** target) const
  370. {
  371. using namespace helper;
  372. RBNode<T>* node = root_;
  373. typename RBTree<T>::Result ret = NOTFOUND;
  374. *up_node = NULLNODE;
  375. isc::dns::Name name = target_name;
  376. while (node != NULLNODE) {
  377. const isc::dns::NameComparisonResult compare_result =
  378. name.compare(node->name_);
  379. const isc::dns::NameComparisonResult::NameRelation relation =
  380. compare_result.getRelation();
  381. if (relation == isc::dns::NameComparisonResult::EQUAL) {
  382. if (!node->isEmpty()) {
  383. *target = node;
  384. ret = EXACTMATCH;
  385. }
  386. break;
  387. } else {
  388. const int common_label_count = compare_result.getCommonLabels();
  389. // If the common label count is 1, there is no common label between
  390. // the two names, except the trailing "dot".
  391. if (common_label_count == 1) {
  392. node = (compare_result.getOrder() < 0) ?
  393. node->left_ : node->right_;
  394. } else if (relation == isc::dns::NameComparisonResult::SUBDOMAIN) {
  395. *up_node = node;
  396. name = name - node->name_;
  397. if (!node->isEmpty()) {
  398. ret = RBTree<T>::PARTIALMATCH;
  399. *target = node;
  400. }
  401. node = node->down_;
  402. } else {
  403. break;
  404. }
  405. }
  406. }
  407. return (ret);
  408. }
  409. template <typename T>
  410. typename RBTree<T>::Result
  411. RBTree<T>::insert(const isc::dns::Name& target_name, RBNode<T>** new_node) {
  412. using namespace helper;
  413. RBNode<T>* parent = NULLNODE;
  414. RBNode<T>* current = root_;
  415. RBNode<T>* up_node = NULLNODE;
  416. isc::dns::Name name = target_name;
  417. int order = -1;
  418. while (current != NULLNODE) {
  419. const isc::dns::NameComparisonResult compare_result =
  420. name.compare(current->name_);
  421. const isc::dns::NameComparisonResult::NameRelation relation =
  422. compare_result.getRelation();
  423. if (relation == isc::dns::NameComparisonResult::EQUAL) {
  424. if (new_node != NULL) {
  425. *new_node = current;
  426. }
  427. return (ALREADYEXIST);
  428. } else {
  429. const int common_label_count = compare_result.getCommonLabels();
  430. if (common_label_count == 1) {
  431. parent = current;
  432. order = compare_result.getOrder();
  433. current = order < 0 ? current->left_ : current->right_;
  434. } else {
  435. // insert sub domain to sub tree
  436. if (relation == isc::dns::NameComparisonResult::SUBDOMAIN) {
  437. parent = NULLNODE;
  438. up_node = current;
  439. name = name - current->name_;
  440. current = current->down_;
  441. } else {
  442. // The number of labels in common is fewer
  443. // than the number of labels at the current
  444. // node, so the current node must be adjusted
  445. // to have just the common suffix, and a down
  446. // pointer made to a new tree.
  447. const isc::dns::Name common_ancestor = name.split(
  448. name.getLabelCount() - common_label_count,
  449. common_label_count);
  450. nodeFission(*current, common_ancestor);
  451. }
  452. }
  453. }
  454. }
  455. RBNode<T>** current_root = (up_node != NULLNODE) ?
  456. &(up_node->down_) : &root_;
  457. // using auto_ptr here is avoid memory leak in case of exceptoin raised
  458. // after the RBNode creation, if we can make sure no exception will be
  459. // raised until the end of the function, we can remove it for optimization
  460. std::auto_ptr<RBNode<T> > node(new RBNode<T>(name));
  461. node->parent_ = parent;
  462. if (parent == NULLNODE) {
  463. *current_root = node.get();
  464. //node is the new root of sub tree, so its init color
  465. // is BLACK
  466. node->color_ = RBNode<T>::BLACK;
  467. } else if (order < 0) {
  468. parent->left_ = node.get();
  469. } else {
  470. parent->right_ = node.get();
  471. }
  472. insertRebalance(current_root, node.get());
  473. if (new_node != NULL) {
  474. *new_node = node.get();
  475. }
  476. ++node_count_;
  477. node.release();
  478. return (SUCCEED);
  479. }
  480. template <typename T>
  481. void
  482. RBTree<T>::nodeFission(RBNode<T>& node, const isc::dns::Name& base_name) {
  483. using namespace helper;
  484. const isc::dns::Name sub_name = node.name_ - base_name;
  485. // using auto_ptr here is to avoid memory leak in case of exceptoin raised
  486. // after the RBNode creation
  487. std::auto_ptr<RBNode<T> > down_node(new RBNode<T>(sub_name));
  488. std::swap(node.data_, down_node->data_);
  489. down_node->down_ = node.down_;
  490. node.name_ = base_name;
  491. node.down_ = down_node.get();
  492. //root node of sub tree, the initial color is BLACK
  493. down_node->color_ = RBNode<T>::BLACK;
  494. ++node_count_;
  495. down_node.release();
  496. }
  497. template <typename T>
  498. void
  499. RBTree<T>::insertRebalance(RBNode<T>** root, RBNode<T>* node) {
  500. RBNode<T>* uncle;
  501. while (node != *root && node->parent_->color_ == RBNode<T>::RED) {
  502. if (node->parent_ == node->parent_->parent_->left_) {
  503. uncle = node->parent_->parent_->right_;
  504. if (uncle->color_ == RBNode<T>::RED) {
  505. node->parent_->color_ = RBNode<T>::BLACK;
  506. uncle->color_ = RBNode<T>::BLACK;
  507. node->parent_->parent_->color_ = RBNode<T>::RED;
  508. node = node->parent_->parent_;
  509. } else {
  510. if (node == node->parent_->right_) {
  511. node = node->parent_;
  512. leftRotate(root, node);
  513. }
  514. node->parent_->color_ = RBNode<T>::BLACK;
  515. node->parent_->parent_->color_ = RBNode<T>::RED;
  516. rightRotate(root, node->parent_->parent_);
  517. }
  518. } else {
  519. uncle = node->parent_->parent_->left_;
  520. if (uncle->color_ == RBNode<T>::RED) {
  521. node->parent_->color_ = RBNode<T>::BLACK;
  522. uncle->color_ = RBNode<T>::BLACK;
  523. node->parent_->parent_->color_ = RBNode<T>::RED;
  524. node = node->parent_->parent_;
  525. } else {
  526. if (node == node->parent_->left_) {
  527. node = node->parent_;
  528. rightRotate(root, node);
  529. }
  530. node->parent_->color_ = RBNode<T>::BLACK;
  531. node->parent_->parent_->color_ = RBNode<T>::RED;
  532. leftRotate(root, node->parent_->parent_);
  533. }
  534. }
  535. }
  536. (*root)->color_ = RBNode<T>::BLACK;
  537. }
  538. template <typename T>
  539. RBNode<T>*
  540. RBTree<T>::leftRotate(RBNode<T>** root, RBNode<T>* node) {
  541. RBNode<T>* right = node->right_;
  542. node->right_ = right->left_;
  543. if (right->left_ != NULLNODE)
  544. right->left_->parent_ = node;
  545. right->parent_ = node->parent_;
  546. if (node->parent_ != NULLNODE) {
  547. if (node == node->parent_->left_) {
  548. node->parent_->left_ = right;
  549. } else {
  550. node->parent_->right_ = right;
  551. }
  552. } else {
  553. *root = right;
  554. }
  555. right->left_ = node;
  556. node->parent_ = right;
  557. return (node);
  558. }
  559. template <typename T>
  560. RBNode<T>*
  561. RBTree<T>::rightRotate(RBNode<T>** root, RBNode<T>* node) {
  562. RBNode<T>* left = node->left_;
  563. node->left_ = left->right_;
  564. if (left->right_ != NULLNODE)
  565. left->right_->parent_ = node;
  566. left->parent_ = node->parent_;
  567. if (node->parent_ != NULLNODE) {
  568. if (node == node->parent_->right_) {
  569. node->parent_->right_ = left;
  570. } else {
  571. node->parent_->left_ = left;
  572. }
  573. } else {
  574. *root = left;
  575. }
  576. left->right_ = node;
  577. node->parent_ = left;
  578. return (node);
  579. }
  580. template <typename T>
  581. void
  582. RBTree<T>::dumpTree(std::ostream& os, unsigned int depth) const {
  583. indent(os, depth);
  584. os << "tree has " << node_count_ << " node(s)\n";
  585. dumpTreeHelper(os, root_, depth);
  586. }
  587. template <typename T>
  588. void
  589. RBTree<T>::dumpTreeHelper(std::ostream& os, const RBNode<T>* node,
  590. unsigned int depth) const
  591. {
  592. if (node == NULLNODE) {
  593. indent(os, depth);
  594. os << "NULL\n";
  595. return;
  596. }
  597. indent(os, depth);
  598. os << node->name_.toText() << " ("
  599. << ((node->color_ == RBNode<T>::BLACK) ? "black" : "red") << ")";
  600. os << ((node->isEmpty()) ? "[invisible] \n" : "\n");
  601. if (node->down_ != NULLNODE) {
  602. indent(os, depth + 1);
  603. os << "begin down from " << node->name_.toText() << "\n";
  604. dumpTreeHelper(os, node->down_, depth + 1);
  605. indent(os, depth + 1);
  606. os << "end down from " << node->name_.toText() << "\n";
  607. }
  608. dumpTreeHelper(os, node->left_, depth + 1);
  609. dumpTreeHelper(os, node->right_, depth + 1);
  610. }
  611. template <typename T>
  612. void
  613. RBTree<T>::indent(std::ostream& os, unsigned int depth) {
  614. static const unsigned int INDENT_FOR_EACH_DEPTH = 5;
  615. os << std::string(depth * INDENT_FOR_EACH_DEPTH, ' ');
  616. }
  617. }
  618. }
  619. #endif // _RBTREE_H
  620. // Local Variables:
  621. // mode: c++
  622. // End: