LCOV - code coverage report
Current view: top level - src - splay-tree-inl.h (source / functions) Hit Total Coverage
Test: app.info Lines: 91 95 95.8 %
Date: 2019-04-17 Functions: 14 22 63.6 %

          Line data    Source code
       1             : // Copyright 2010 the V8 project authors. All rights reserved.
       2             : // Use of this source code is governed by a BSD-style license that can be
       3             : // found in the LICENSE file.
       4             : 
       5             : #ifndef V8_SPLAY_TREE_INL_H_
       6             : #define V8_SPLAY_TREE_INL_H_
       7             : 
       8             : #include <vector>
       9             : 
      10             : #include "src/splay-tree.h"
      11             : 
      12             : namespace v8 {
      13             : namespace internal {
      14             : 
      15             : 
      16             : template<typename Config, class Allocator>
      17             : SplayTree<Config, Allocator>::~SplayTree() {
      18             :   NodeDeleter deleter;
      19        2652 :   ForEachNode(&deleter);
      20        2652 : }
      21             : 
      22             : 
      23             : template<typename Config, class Allocator>
      24      163721 : bool SplayTree<Config, Allocator>::Insert(const Key& key,
      25             :                                           Locator* locator) {
      26      163721 :   if (is_empty()) {
      27             :     // If the tree is empty, insert the new node.
      28        5304 :     root_ = new(allocator_) Node(key, Config::NoValue());
      29             :   } else {
      30             :     // Splay on the key to move the last node on the search path
      31             :     // for the key to the root of the tree.
      32      161069 :     Splay(key);
      33             :     // Ignore repeated insertions with the same key.
      34      161069 :     int cmp = Config::Compare(key, root_->key_);
      35      161069 :     if (cmp == 0) {
      36             :       locator->bind(root_);
      37           0 :       return false;
      38             :     }
      39             :     // Insert the new node.
      40      161069 :     Node* node = new(allocator_) Node(key, Config::NoValue());
      41             :     InsertInternal(cmp, node);
      42             :   }
      43      163721 :   locator->bind(root_);
      44      163721 :   return true;
      45             : }
      46             : 
      47             : 
      48             : template<typename Config, class Allocator>
      49             : void SplayTree<Config, Allocator>::InsertInternal(int cmp, Node* node) {
      50      161069 :   if (cmp > 0) {
      51      153677 :     node->left_ = root_;
      52      153677 :     node->right_ = root_->right_;
      53      153677 :     root_->right_ = nullptr;
      54             :   } else {
      55        7392 :     node->right_ = root_;
      56        7392 :     node->left_ = root_->left_;
      57        7392 :     root_->left_ = nullptr;
      58             :   }
      59      161069 :   root_ = node;
      60             : }
      61             : 
      62             : 
      63             : template<typename Config, class Allocator>
      64     1066150 : bool SplayTree<Config, Allocator>::FindInternal(const Key& key) {
      65     1066150 :   if (is_empty())
      66             :     return false;
      67     1066145 :   Splay(key);
      68     2132290 :   return Config::Compare(key, root_->key_) == 0;
      69             : }
      70             : 
      71             : 
      72             : template<typename Config, class Allocator>
      73             : bool SplayTree<Config, Allocator>::Contains(const Key& key) {
      74             :   return FindInternal(key);
      75             : }
      76             : 
      77             : 
      78             : template<typename Config, class Allocator>
      79             : bool SplayTree<Config, Allocator>::Find(const Key& key, Locator* locator) {
      80     1066065 :   if (FindInternal(key)) {
      81       90190 :     locator->bind(root_);
      82             :     return true;
      83             :   } else {
      84             :     return false;
      85             :   }
      86             : }
      87             : 
      88             : 
      89             : template<typename Config, class Allocator>
      90      141901 : bool SplayTree<Config, Allocator>::FindGreatestLessThan(const Key& key,
      91             :                                                         Locator* locator) {
      92      141901 :   if (is_empty())
      93             :     return false;
      94             :   // Splay on the key to move the node with the given key or the last
      95             :   // node on the search path to the top of the tree.
      96      141901 :   Splay(key);
      97             :   // Now the result is either the root node or the greatest node in
      98             :   // the left subtree.
      99      141901 :   int cmp = Config::Compare(root_->key_, key);
     100      141901 :   if (cmp <= 0) {
     101             :     locator->bind(root_);
     102      111319 :     return true;
     103             :   } else {
     104             :     Node* temp = root_;
     105       30582 :     root_ = root_->left_;
     106             :     bool result = FindGreatest(locator);
     107       30582 :     root_ = temp;
     108       30582 :     return result;
     109             :   }
     110             : }
     111             : 
     112             : 
     113             : template<typename Config, class Allocator>
     114      163169 : bool SplayTree<Config, Allocator>::FindLeastGreaterThan(const Key& key,
     115             :                                                         Locator* locator) {
     116      163169 :   if (is_empty())
     117             :     return false;
     118             :   // Splay on the key to move the node with the given key or the last
     119             :   // node on the search path to the top of the tree.
     120      163169 :   Splay(key);
     121             :   // Now the result is either the root node or the least node in
     122             :   // the right subtree.
     123      163169 :   int cmp = Config::Compare(root_->key_, key);
     124      163169 :   if (cmp >= 0) {
     125             :     locator->bind(root_);
     126       82248 :     return true;
     127             :   } else {
     128             :     Node* temp = root_;
     129       80921 :     root_ = root_->right_;
     130             :     bool result = FindLeast(locator);
     131       80921 :     root_ = temp;
     132       80921 :     return result;
     133             :   }
     134             : }
     135             : 
     136             : 
     137             : template<typename Config, class Allocator>
     138             : bool SplayTree<Config, Allocator>::FindGreatest(Locator* locator) {
     139       30582 :   if (is_empty())
     140             :     return false;
     141             :   Node* current = root_;
     142       29130 :   while (current->right_ != nullptr) current = current->right_;
     143             :   locator->bind(current);
     144             :   return true;
     145             : }
     146             : 
     147             : 
     148             : template<typename Config, class Allocator>
     149             : bool SplayTree<Config, Allocator>::FindLeast(Locator* locator) {
     150       80921 :   if (is_empty())
     151             :     return false;
     152             :   Node* current = root_;
     153        2900 :   while (current->left_ != nullptr) current = current->left_;
     154             :   locator->bind(current);
     155             :   return true;
     156             : }
     157             : 
     158             : 
     159             : template<typename Config, class Allocator>
     160             : bool SplayTree<Config, Allocator>::Move(const Key& old_key,
     161             :                                         const Key& new_key) {
     162             :   if (!FindInternal(old_key))
     163             :     return false;
     164             :   Node* node_to_move = root_;
     165             :   RemoveRootNode(old_key);
     166             :   Splay(new_key);
     167             :   int cmp = Config::Compare(new_key, root_->key_);
     168             :   if (cmp == 0) {
     169             :     // A node with the target key already exists.
     170             :     delete node_to_move;
     171             :     return false;
     172             :   }
     173             :   node_to_move->key_ = new_key;
     174             :   InsertInternal(cmp, node_to_move);
     175             :   return true;
     176             : }
     177             : 
     178             : 
     179             : template<typename Config, class Allocator>
     180          85 : bool SplayTree<Config, Allocator>::Remove(const Key& key) {
     181          85 :   if (!FindInternal(key))
     182             :     return false;
     183           0 :   Node* node_to_remove = root_;
     184          85 :   RemoveRootNode(key);
     185             :   delete node_to_remove;
     186          85 :   return true;
     187             : }
     188             : 
     189             : 
     190             : template<typename Config, class Allocator>
     191          85 : void SplayTree<Config, Allocator>::RemoveRootNode(const Key& key) {
     192          85 :   if (root_->left_ == nullptr) {
     193             :     // No left child, so the new tree is just the right child.
     194           0 :     root_ = root_->right_;
     195             :   } else {
     196             :     // Left child exists.
     197          85 :     Node* right = root_->right_;
     198             :     // Make the original left child the new root.
     199          85 :     root_ = root_->left_;
     200             :     // Splay to make sure that the new root has an empty right child.
     201          85 :     Splay(key);
     202             :     // Insert the original right child as the right child of the new
     203             :     // root.
     204          85 :     root_->right_ = right;
     205             :   }
     206          85 : }
     207             : 
     208             : 
     209             : template<typename Config, class Allocator>
     210     1532369 : void SplayTree<Config, Allocator>::Splay(const Key& key) {
     211     1532369 :   if (is_empty())
     212           0 :     return;
     213             :   Node dummy_node(Config::kNoKey, Config::NoValue());
     214             :   // Create a dummy node.  The use of the dummy node is a bit
     215             :   // counter-intuitive: The right child of the dummy node will hold
     216             :   // the L tree of the algorithm.  The left child of the dummy node
     217             :   // will hold the R tree of the algorithm.  Using a dummy node, left
     218             :   // and right will always be nodes and we avoid special cases.
     219             :   Node* dummy = &dummy_node;
     220             :   Node* left = dummy;
     221             :   Node* right = dummy;
     222             :   Node* current = root_;
     223             :   while (true) {
     224     2984501 :     int cmp = Config::Compare(key, current->key_);
     225     2984501 :     if (cmp < 0) {
     226     1395108 :       if (current->left_ == nullptr) break;
     227     1702664 :       if (Config::Compare(key, current->left_->key_) < 0) {
     228             :         // Rotate right.
     229             :         Node* temp = current->left_;
     230      284681 :         current->left_ = temp->right_;
     231      284681 :         temp->right_ = current;
     232             :         current = temp;
     233      284681 :         if (current->left_ == nullptr) break;
     234             :       }
     235             :       // Link right.
     236      786321 :       right->left_ = current;
     237             :       right = current;
     238      786321 :       current = current->left_;
     239     1589393 :     } else if (cmp > 0) {
     240     1474508 :       if (current->right_ == nullptr) break;
     241     1335656 :       if (Config::Compare(key, current->right_->key_) > 0) {
     242             :         // Rotate left.
     243             :         Node* temp = current->right_;
     244       74323 :         current->right_ = temp->left_;
     245       74323 :         temp->left_ = current;
     246             :         current = temp;
     247       74323 :         if (current->right_ == nullptr) break;
     248             :       }
     249             :       // Link left.
     250      665811 :       left->right_ = current;
     251             :       left = current;
     252      665811 :       current = current->right_;
     253             :     } else {
     254             :       break;
     255             :     }
     256             :   }
     257             :   // Assemble.
     258     1532369 :   left->right_ = current->left_;
     259     1532369 :   right->left_ = current->right_;
     260     1532369 :   current->left_ = dummy->right_;
     261     1532369 :   current->right_ = dummy->left_;
     262     1532369 :   root_ = current;
     263             : }
     264             : 
     265             : 
     266             : template <typename Config, class Allocator> template <class Callback>
     267             : void SplayTree<Config, Allocator>::ForEach(Callback* callback) {
     268             :   NodeToPairAdaptor<Callback> callback_adaptor(callback);
     269        2587 :   ForEachNode(&callback_adaptor);
     270             : }
     271             : 
     272             : 
     273             : template <typename Config, class Allocator> template <class Callback>
     274        5239 : void SplayTree<Config, Allocator>::ForEachNode(Callback* callback) {
     275        7891 :   if (root_ == nullptr) return;
     276             :   // Pre-allocate some space for tiny trees.
     277             :   std::vector<Node*> nodes_to_visit;
     278        2587 :   nodes_to_visit.push_back(root_);
     279             :   size_t pos = 0;
     280      324669 :   while (pos < nodes_to_visit.size()) {
     281      322082 :     Node* node = nodes_to_visit[pos++];
     282      319120 :     if (node->left() != nullptr) nodes_to_visit.push_back(node->left());
     283      161416 :     if (node->right() != nullptr) nodes_to_visit.push_back(node->right());
     284      161041 :     callback->Call(node);
     285             :   }
     286             : }
     287             : 
     288             : 
     289             : }  // namespace internal
     290             : }  // namespace v8
     291             : 
     292             : #endif  // V8_SPLAY_TREE_INL_H_

Generated by: LCOV version 1.10