avl.h
Go to the documentation of this file.
1 // Copyright 2021 gRPC authors.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 #ifndef GRPC_CORE_LIB_AVL_AVL_H
16 #define GRPC_CORE_LIB_AVL_AVL_H
17 
19 
20 #include <stdlib.h>
21 
22 #include <algorithm> // IWYU pragma: keep
23 #include <memory>
24 #include <utility>
25 #include <vector>
26 
27 namespace grpc_core {
28 
29 template <class K, class V = void>
30 class AVL {
31  public:
32  AVL() {}
33 
34  AVL Add(K key, V value) const {
36  }
37  template <typename SomethingLikeK>
38  AVL Remove(const SomethingLikeK& key) const {
39  return AVL(RemoveKey(root_, key));
40  }
41  template <typename SomethingLikeK>
42  const V* Lookup(const SomethingLikeK& key) const {
43  NodePtr n = Get(root_, key);
44  return n ? &n->kv.second : nullptr;
45  }
46 
47  const std::pair<K, V>* LookupBelow(const K& key) const {
48  NodePtr n = GetBelow(root_, *key);
49  return n ? &n->kv : nullptr;
50  }
51 
52  bool Empty() const { return root_ == nullptr; }
53 
54  template <class F>
55  void ForEach(F&& f) const {
56  ForEachImpl(root_.get(), std::forward<F>(f));
57  }
58 
59  bool SameIdentity(const AVL& avl) const { return root_ == avl.root_; }
60 
61  bool operator==(const AVL& other) const {
62  Iterator a(root_);
63  Iterator b(other.root_);
64  for (;;) {
65  Node* p = a.current();
66  Node* q = b.current();
67  if (p == nullptr) return q == nullptr;
68  if (q == nullptr) return false;
69  if (p->kv != q->kv) return false;
70  a.MoveNext();
71  b.MoveNext();
72  }
73  }
74 
75  bool operator<(const AVL& other) const {
76  Iterator a(root_);
77  Iterator b(other.root_);
78  for (;;) {
79  Node* p = a.current();
80  Node* q = b.current();
81  if (p == nullptr) return q != nullptr;
82  if (q == nullptr) return false;
83  if (p->kv < q->kv) return true;
84  if (p->kv != q->kv) return false;
85  a.MoveNext();
86  b.MoveNext();
87  }
88  }
89 
90  private:
91  struct Node;
92 
93  typedef std::shared_ptr<Node> NodePtr;
94  struct Node : public std::enable_shared_from_this<Node> {
95  Node(K k, V v, NodePtr l, NodePtr r, long h)
96  : kv(std::move(k), std::move(v)),
97  left(std::move(l)),
98  right(std::move(r)),
99  height(h) {}
100  const std::pair<K, V> kv;
101  const NodePtr left;
102  const NodePtr right;
103  const long height;
104  };
106 
107  class Iterator {
108  public:
109  explicit Iterator(const NodePtr& root) {
110  auto* n = root.get();
111  while (n != nullptr) {
112  stack_.push_back(n);
113  n = n->left.get();
114  }
115  }
116  Node* current() const { return stack_.empty() ? nullptr : stack_.back(); }
117  void MoveNext() {
118  auto* n = stack_.back();
119  stack_.pop_back();
120  if (n->right != nullptr) {
121  n = n->right.get();
122  while (n != nullptr) {
123  stack_.push_back(n);
124  n = n->left.get();
125  }
126  }
127  }
128 
129  private:
130  std::vector<Node*> stack_;
131  };
132 
133  explicit AVL(NodePtr root) : root_(std::move(root)) {}
134 
135  template <class F>
136  static void ForEachImpl(const Node* n, F&& f) {
137  if (n == nullptr) return;
138  ForEachImpl(n->left.get(), std::forward<F>(f));
139  f(const_cast<const K&>(n->kv.first), const_cast<const V&>(n->kv.second));
140  ForEachImpl(n->right.get(), std::forward<F>(f));
141  }
142 
143  static long Height(const NodePtr& n) { return n ? n->height : 0; }
144 
145  static NodePtr MakeNode(K key, V value, const NodePtr& left,
146  const NodePtr& right) {
147  return std::make_shared<Node>(std::move(key), std::move(value), left, right,
148  1 + std::max(Height(left), Height(right)));
149  }
150 
151  template <typename SomethingLikeK>
152  static NodePtr Get(const NodePtr& node, const SomethingLikeK& key) {
153  if (node == nullptr) {
154  return nullptr;
155  }
156 
157  if (node->kv.first > key) {
158  return Get(node->left, key);
159  } else if (node->kv.first < key) {
160  return Get(node->right, key);
161  } else {
162  return node;
163  }
164  }
165 
166  static NodePtr GetBelow(const NodePtr& node, const K& key) {
167  if (!node) return nullptr;
168  if (node->kv.first > key) {
169  return GetBelow(node->left, key);
170  } else if (node->kv.first < key) {
171  NodePtr n = GetBelow(node->right, key);
172  if (n == nullptr) n = node;
173  return n;
174  } else {
175  return node;
176  }
177  }
178 
179  static NodePtr RotateLeft(K key, V value, const NodePtr& left,
180  const NodePtr& right) {
181  return MakeNode(
182  right->kv.first, right->kv.second,
183  MakeNode(std::move(key), std::move(value), left, right->left),
184  right->right);
185  }
186 
187  static NodePtr RotateRight(K key, V value, const NodePtr& left,
188  const NodePtr& right) {
189  return MakeNode(
190  left->kv.first, left->kv.second, left->left,
191  MakeNode(std::move(key), std::move(value), left->right, right));
192  }
193 
194  static NodePtr RotateLeftRight(K key, V value, const NodePtr& left,
195  const NodePtr& right) {
196  /* rotate_right(..., rotate_left(left), right) */
197  return MakeNode(
198  left->right->kv.first, left->right->kv.second,
199  MakeNode(left->kv.first, left->kv.second, left->left,
200  left->right->left),
201  MakeNode(std::move(key), std::move(value), left->right->right, right));
202  }
203 
204  static NodePtr RotateRightLeft(K key, V value, const NodePtr& left,
205  const NodePtr& right) {
206  /* rotate_left(..., left, rotate_right(right)) */
207  return MakeNode(
208  right->left->kv.first, right->left->kv.second,
209  MakeNode(std::move(key), std::move(value), left, right->left->left),
210  MakeNode(right->kv.first, right->kv.second, right->left->right,
211  right->right));
212  }
213 
214  static NodePtr Rebalance(K key, V value, const NodePtr& left,
215  const NodePtr& right) {
216  switch (Height(left) - Height(right)) {
217  case 2:
218  if (Height(left->left) - Height(left->right) == -1) {
219  return RotateLeftRight(std::move(key), std::move(value), left, right);
220  } else {
221  return RotateRight(std::move(key), std::move(value), left, right);
222  }
223  case -2:
224  if (Height(right->left) - Height(right->right) == 1) {
225  return RotateRightLeft(std::move(key), std::move(value), left, right);
226  } else {
227  return RotateLeft(std::move(key), std::move(value), left, right);
228  }
229  default:
230  return MakeNode(key, value, left, right);
231  }
232  }
233 
234  static NodePtr AddKey(const NodePtr& node, K key, V value) {
235  if (!node) {
236  return MakeNode(std::move(key), std::move(value), nullptr, nullptr);
237  }
238  if (node->kv.first < key) {
239  return Rebalance(node->kv.first, node->kv.second, node->left,
240  AddKey(node->right, std::move(key), std::move(value)));
241  }
242  if (key < node->kv.first) {
243  return Rebalance(node->kv.first, node->kv.second,
244  AddKey(node->left, std::move(key), std::move(value)),
245  node->right);
246  }
247  return MakeNode(std::move(key), std::move(value), node->left, node->right);
248  }
249 
250  static NodePtr InOrderHead(NodePtr node) {
251  while (node->left != nullptr) {
252  node = node->left;
253  }
254  return node;
255  }
256 
257  static NodePtr InOrderTail(NodePtr node) {
258  while (node->right != nullptr) {
259  node = node->right;
260  }
261  return node;
262  }
263 
264  template <typename SomethingLikeK>
265  static NodePtr RemoveKey(const NodePtr& node, const SomethingLikeK& key) {
266  if (node == nullptr) {
267  return nullptr;
268  }
269  if (key < node->kv.first) {
270  return Rebalance(node->kv.first, node->kv.second,
271  RemoveKey(node->left, key), node->right);
272  } else if (node->kv.first < key) {
273  return Rebalance(node->kv.first, node->kv.second, node->left,
274  RemoveKey(node->right, key));
275  } else {
276  if (node->left == nullptr) {
277  return node->right;
278  } else if (node->right == nullptr) {
279  return node->left;
280  } else if (node->left->height < node->right->height) {
281  NodePtr h = InOrderHead(node->right);
282  return Rebalance(h->kv.first, h->kv.second, node->left,
283  RemoveKey(node->right, h->kv.first));
284  } else {
285  NodePtr h = InOrderTail(node->left);
286  return Rebalance(h->kv.first, h->kv.second,
287  RemoveKey(node->left, h->kv.first), node->right);
288  }
289  }
290  abort();
291  }
292 };
293 
294 template <class K>
295 class AVL<K, void> {
296  public:
297  AVL() {}
298 
299  AVL Add(K key) const { return AVL(AddKey(root_, std::move(key))); }
300  AVL Remove(const K& key) const { return AVL(RemoveKey(root_, key)); }
301  bool Lookup(const K& key) const { return Get(root_, key) != nullptr; }
302  bool Empty() const { return root_ == nullptr; }
303 
304  template <class F>
305  void ForEach(F&& f) const {
306  ForEachImpl(root_.get(), std::forward<F>(f));
307  }
308 
309  bool SameIdentity(AVL avl) const { return root_ == avl.root_; }
310 
311  private:
312  struct Node;
313 
314  typedef std::shared_ptr<Node> NodePtr;
315  struct Node : public std::enable_shared_from_this<Node> {
316  Node(K k, NodePtr l, NodePtr r, long h)
317  : key(std::move(k)),
318  left(std::move(l)),
319  right(std::move(r)),
320  height(h) {}
321  const K key;
322  const NodePtr left;
323  const NodePtr right;
324  const long height;
325  };
327 
328  explicit AVL(NodePtr root) : root_(std::move(root)) {}
329 
330  template <class F>
331  static void ForEachImpl(const Node* n, F&& f) {
332  if (n == nullptr) return;
333  ForEachImpl(n->left.get(), std::forward<F>(f));
334  f(const_cast<const K&>(n->key));
335  ForEachImpl(n->right.get(), std::forward<F>(f));
336  }
337 
338  static long Height(const NodePtr& n) { return n ? n->height : 0; }
339 
340  static NodePtr MakeNode(K key, const NodePtr& left, const NodePtr& right) {
341  return std::make_shared<Node>(std::move(key), left, right,
342  1 + std::max(Height(left), Height(right)));
343  }
344 
345  static NodePtr Get(const NodePtr& node, const K& key) {
346  if (node == nullptr) {
347  return nullptr;
348  }
349 
350  if (node->key > key) {
351  return Get(node->left, key);
352  } else if (node->key < key) {
353  return Get(node->right, key);
354  } else {
355  return node;
356  }
357  }
358 
359  static NodePtr RotateLeft(K key, const NodePtr& left, const NodePtr& right) {
360  return MakeNode(right->key, MakeNode(std::move(key), left, right->left),
361  right->right);
362  }
363 
364  static NodePtr RotateRight(K key, const NodePtr& left, const NodePtr& right) {
365  return MakeNode(left->key, left->left,
366  MakeNode(std::move(key), left->right, right));
367  }
368 
369  static NodePtr RotateLeftRight(K key, const NodePtr& left,
370  const NodePtr& right) {
371  /* rotate_right(..., rotate_left(left), right) */
372  return MakeNode(left->right->key,
373  MakeNode(left->key, left->left, left->right->left),
374  MakeNode(std::move(key), left->right->right, right));
375  }
376 
377  static NodePtr RotateRightLeft(K key, const NodePtr& left,
378  const NodePtr& right) {
379  /* rotate_left(..., left, rotate_right(right)) */
380  return MakeNode(right->left->key,
381  MakeNode(std::move(key), left, right->left->left),
382  MakeNode(right->key, right->left->right, right->right));
383  }
384 
385  static NodePtr Rebalance(K key, const NodePtr& left, const NodePtr& right) {
386  switch (Height(left) - Height(right)) {
387  case 2:
388  if (Height(left->left) - Height(left->right) == -1) {
389  return RotateLeftRight(std::move(key), left, right);
390  } else {
391  return RotateRight(std::move(key), left, right);
392  }
393  case -2:
394  if (Height(right->left) - Height(right->right) == 1) {
395  return RotateRightLeft(std::move(key), left, right);
396  } else {
397  return RotateLeft(std::move(key), left, right);
398  }
399  default:
400  return MakeNode(key, left, right);
401  }
402  }
403 
404  static NodePtr AddKey(const NodePtr& node, K key) {
405  if (!node) {
406  return MakeNode(std::move(key), nullptr, nullptr);
407  }
408  if (node->key < key) {
409  return Rebalance(node->key, node->left,
410  AddKey(node->right, std::move(key)));
411  }
412  if (key < node->key) {
413  return Rebalance(node->key, AddKey(node->left, std::move(key)),
414  node->right);
415  }
416  return MakeNode(std::move(key), node->left, node->right);
417  }
418 
419  static NodePtr InOrderHead(NodePtr node) {
420  while (node->left != nullptr) {
421  node = node->left;
422  }
423  return node;
424  }
425 
426  static NodePtr InOrderTail(NodePtr node) {
427  while (node->right != nullptr) {
428  node = node->right;
429  }
430  return node;
431  }
432 
433  static NodePtr RemoveKey(const NodePtr& node, const K& key) {
434  if (node == nullptr) {
435  return nullptr;
436  }
437  if (key < node->key) {
438  return Rebalance(node->key, RemoveKey(node->left, key), node->right);
439  } else if (node->key < key) {
440  return Rebalance(node->key, node->left, RemoveKey(node->right, key));
441  } else {
442  if (node->left == nullptr) {
443  return node->right;
444  } else if (node->right == nullptr) {
445  return node->left;
446  } else if (node->left->height < node->right->height) {
447  NodePtr h = InOrderHead(node->right);
448  return Rebalance(h->key, node->left, RemoveKey(node->right, h->key));
449  } else {
450  NodePtr h = InOrderTail(node->left);
451  return Rebalance(h->key, RemoveKey(node->left, h->key), node->right);
452  }
453  }
454  abort();
455  }
456 };
457 
458 } // namespace grpc_core
459 
460 #endif // GRPC_CORE_LIB_AVL_AVL_H
grpc_core::AVL< K, void >::Get
static NodePtr Get(const NodePtr &node, const K &key)
Definition: avl.h:345
grpc_core::AVL::Rebalance
static NodePtr Rebalance(K key, V value, const NodePtr &left, const NodePtr &right)
Definition: avl.h:214
grpc_core::AVL::Height
static long Height(const NodePtr &n)
Definition: avl.h:143
grpc_core::AVL::AVL
AVL(NodePtr root)
Definition: avl.h:133
grpc_core::AVL::Node::left
const NodePtr left
Definition: avl.h:101
opencensus.proto.agent.common.v1.common_pb2.Node
Node
Definition: common_pb2.py:308
grpc_core::AVL< K, void >::Rebalance
static NodePtr Rebalance(K key, const NodePtr &left, const NodePtr &right)
Definition: avl.h:385
grpc_core::AVL::Iterator
Definition: avl.h:107
grpc_core::AVL< K, void >::Height
static long Height(const NodePtr &n)
Definition: avl.h:338
grpc_core::AVL::Lookup
const V * Lookup(const SomethingLikeK &key) const
Definition: avl.h:42
grpc_core::RefCountedPtr::get
T * get() const
Definition: ref_counted_ptr.h:146
grpc_core
Definition: call_metric_recorder.h:31
grpc_core::AVL::InOrderTail
static NodePtr InOrderTail(NodePtr node)
Definition: avl.h:257
grpc_core::AVL::AddKey
static NodePtr AddKey(const NodePtr &node, K key, V value)
Definition: avl.h:234
grpc_core::AVL< K, void >::MakeNode
static NodePtr MakeNode(K key, const NodePtr &left, const NodePtr &right)
Definition: avl.h:340
a
int a
Definition: abseil-cpp/absl/container/internal/hash_policy_traits_test.cc:88
grpc_core::AVL< K, void >::Lookup
bool Lookup(const K &key) const
Definition: avl.h:301
grpc_core::AVL::RotateRight
static NodePtr RotateRight(K key, V value, const NodePtr &left, const NodePtr &right)
Definition: avl.h:187
grpc_core::AVL< K, void >::NodePtr
std::shared_ptr< Node > NodePtr
Definition: avl.h:312
grpc_core::AVL< K, void >::RotateLeft
static NodePtr RotateLeft(K key, const NodePtr &left, const NodePtr &right)
Definition: avl.h:359
setup.k
k
Definition: third_party/bloaty/third_party/capstone/bindings/python/setup.py:42
grpc_core::AVL::SameIdentity
bool SameIdentity(const AVL &avl) const
Definition: avl.h:59
grpc_core::AVL::Remove
AVL Remove(const SomethingLikeK &key) const
Definition: avl.h:38
grpc_core::AVL< K, void >::RotateLeftRight
static NodePtr RotateLeftRight(K key, const NodePtr &left, const NodePtr &right)
Definition: avl.h:369
grpc_core::AVL::ForEachImpl
static void ForEachImpl(const Node *n, F &&f)
Definition: avl.h:136
grpc_core::AVL< K, void >::Remove
AVL Remove(const K &key) const
Definition: avl.h:300
grpc_core::AVL::Iterator::current
Node * current() const
Definition: avl.h:116
absl::move
constexpr absl::remove_reference_t< T > && move(T &&t) noexcept
Definition: abseil-cpp/absl/utility/utility.h:221
grpc_core::AVL::Node::Node
Node(K k, V v, NodePtr l, NodePtr r, long h)
Definition: avl.h:95
max
int max
Definition: bloaty/third_party/zlib/examples/enough.c:170
root
RefCountedPtr< grpc_tls_certificate_provider > root
Definition: xds_server_config_fetcher.cc:223
grpc_core::AVL::operator==
bool operator==(const AVL &other) const
Definition: avl.h:61
grpc_core::AVL< K, void >::AVL
AVL(NodePtr root)
Definition: avl.h:328
setup.v
v
Definition: third_party/bloaty/third_party/capstone/bindings/python/setup.py:42
grpc_core::AVL::Iterator::stack_
std::vector< Node * > stack_
Definition: avl.h:130
grpc_core::AVL::Add
AVL Add(K key, V value) const
Definition: avl.h:34
grpc_core::AVL< K, void >::Node::Node
Node(K k, NodePtr l, NodePtr r, long h)
Definition: avl.h:316
grpc_core::AVL< K, void >::InOrderTail
static NodePtr InOrderTail(NodePtr node)
Definition: avl.h:426
grpc_core::AVL< K, void >::SameIdentity
bool SameIdentity(AVL avl) const
Definition: avl.h:309
grpc_core::AVL::RotateLeftRight
static NodePtr RotateLeftRight(K key, V value, const NodePtr &left, const NodePtr &right)
Definition: avl.h:194
grpc_core::AVL< std::string, absl::variant >::NodePtr
std::shared_ptr< Node > NodePtr
Definition: avl.h:91
grpc_core::AVL::Node::kv
const std::pair< K, V > kv
Definition: avl.h:100
grpc_core::AVL::RotateLeft
static NodePtr RotateLeft(K key, V value, const NodePtr &left, const NodePtr &right)
Definition: avl.h:179
grpc_core::AVL< K, void >::ForEach
void ForEach(F &&f) const
Definition: avl.h:305
grpc_core::AVL::operator<
bool operator<(const AVL &other) const
Definition: avl.h:75
b
uint64_t b
Definition: abseil-cpp/absl/container/internal/layout_test.cc:53
grpc_core::AVL::InOrderHead
static NodePtr InOrderHead(NodePtr node)
Definition: avl.h:250
grpc_core::AVL::Iterator::Iterator
Iterator(const NodePtr &root)
Definition: avl.h:109
grpc_core::AVL< K, void >::root_
NodePtr root_
Definition: avl.h:326
grpc_core::AVL< K, void >::InOrderHead
static NodePtr InOrderHead(NodePtr node)
Definition: avl.h:419
n
int n
Definition: abseil-cpp/absl/container/btree_test.cc:1080
grpc_core::AVL::AVL
AVL()
Definition: avl.h:32
value
const char * value
Definition: hpack_parser_table.cc:165
grpc_core::AVL
Definition: avl.h:30
grpc_core::AVL< K, void >::Node::key
const K key
Definition: avl.h:321
grpc_core::AVL::Empty
bool Empty() const
Definition: avl.h:52
grpc_core::AVL< K, void >::AVL
AVL()
Definition: avl.h:297
grpc_core::AVL::Iterator::MoveNext
void MoveNext()
Definition: avl.h:117
key
const char * key
Definition: hpack_parser_table.cc:164
grpc_core::AVL::ForEach
void ForEach(F &&f) const
Definition: avl.h:55
grpc_core::AVL::LookupBelow
const std::pair< K, V > * LookupBelow(const K &key) const
Definition: avl.h:47
grpc_core::AVL::Node
Definition: avl.h:94
grpc_core::AVL< K, void >::AddKey
static NodePtr AddKey(const NodePtr &node, K key)
Definition: avl.h:404
grpc_core::AVL< K, void >::Empty
bool Empty() const
Definition: avl.h:302
fix_build_deps.r
r
Definition: fix_build_deps.py:491
std
Definition: grpcpp/impl/codegen/async_unary_call.h:407
grpc_core::AVL< K, void >::Node::left
const NodePtr left
Definition: avl.h:322
grpc_core::AVL< K, void >::Node::height
const long height
Definition: avl.h:324
absl::inlined_vector_internal::Iterator
Pointer< A > Iterator
Definition: abseil-cpp/absl/container/internal/inlined_vector.h:64
grpc_core::AVL< K, void >::RotateRightLeft
static NodePtr RotateRightLeft(K key, const NodePtr &left, const NodePtr &right)
Definition: avl.h:377
grpc_core::AVL< K, void >::RemoveKey
static NodePtr RemoveKey(const NodePtr &node, const K &key)
Definition: avl.h:433
grpc_core::AVL::RotateRightLeft
static NodePtr RotateRightLeft(K key, V value, const NodePtr &left, const NodePtr &right)
Definition: avl.h:204
grpc_core::AVL::MakeNode
static NodePtr MakeNode(K key, V value, const NodePtr &left, const NodePtr &right)
Definition: avl.h:145
grpc_core::AVL::root_
NodePtr root_
Definition: avl.h:105
grpc_core::AVL::Get
static NodePtr Get(const NodePtr &node, const SomethingLikeK &key)
Definition: avl.h:152
grpc_core::AVL::Node::height
const long height
Definition: avl.h:103
grpc_core::AVL::GetBelow
static NodePtr GetBelow(const NodePtr &node, const K &key)
Definition: avl.h:166
grpc_core::AVL< K, void >::RotateRight
static NodePtr RotateRight(K key, const NodePtr &left, const NodePtr &right)
Definition: avl.h:364
grpc_core::AVL< K, void >::Add
AVL Add(K key) const
Definition: avl.h:299
grpc_core::AVL< K, void >::ForEachImpl
static void ForEachImpl(const Node *n, F &&f)
Definition: avl.h:331
grpc_core::AVL::Node::right
const NodePtr right
Definition: avl.h:102
grpc_core::AVL< K, void >::Node::right
const NodePtr right
Definition: avl.h:323
grpc_core::AVL::RemoveKey
static NodePtr RemoveKey(const NodePtr &node, const SomethingLikeK &key)
Definition: avl.h:265
port_platform.h


grpc
Author(s):
autogenerated on Thu Mar 13 2025 02:58:35