MeVisLab Toolbox Reference
mlContainers.h
Go to the documentation of this file.
1 /*************************************************************************************
2 **
3 ** Copyright 2022, MeVis Medical Solutions AG
4 **
5 ** The user may use this file in accordance with the license agreement provided with
6 ** the Software or, alternatively, in accordance with the terms contained in a
7 ** written agreement between the user and MeVis Medical Solutions AG.
8 **
9 ** For further information use the contact form at https://www.mevislab.de/contact
10 **
11 **************************************************************************************/
12 
13 #pragma once
14 
15 #include "mlUtilsSystem.h"
16 #include <algorithm>
17 #include <vector>
18 
19 ML_UTILS_START_NAMESPACE
20 
21 /*
22  * A structure that implements a value based tree
23  */
24 template <typename T> struct tree_node
25 {
27  std::vector<tree_node> children;
28 };
29 
30 /*
31  * Flattens the given tree into a vector of elements
32  */
33 template <typename T> void flatten(const tree_node<T> &tree, std::vector<T> &flatten_elements)
34 {
35  flatten_elements.push_back(tree.value);
36  for (const auto &child : tree.children)
37  {
38  flatten(child, flatten_elements);
39  }
40 }
41 
42 /*
43  * Insert the given element into the tree as set operation
44  * operator<, operator>= and operator== for the elements must be defined for the insertion
45  * operation. operator== is only needed to identify an element to be zero
46  * @param tree The tree that shall be filled
47  * @param newValue The new value that shall be put into the tree
48  * @param zero A value that identifies an object of T as empty
49  */
50 template <typename T>
51 void insert_set_sorted(tree_node<T> &tree, T newValue, T zero = {})
52 {
53  // Is the new element smaller than the root => Insert new root and add the tree as child
54  if (tree.value < newValue)
55  {
56  tree_node<T> newRoot;
57  insert_set_sorted(newRoot, std::move(newValue));
58 
59  std::swap(tree, newRoot);
60 
61  tree.children.emplace_back(tree_node<T>{std::move(newRoot)});
62  return;
63  }
64  bool reparent{};
65  for (auto &child : tree.children)
66  {
67  if (child.value >= newValue)
68  {
69  insert_set_sorted(child, std::move(newValue));
70  return;
71  }
72 
73  // Is the child smaller than the new one
74  if (newValue >= child.value)
75  {
76  reparent = true;
77  break;
78  }
79  }
80 
81  if (reparent)
82  {
83  // move the smaller childs to the end
84  auto itToMoved =
85  std::stable_partition(tree.children.begin(), tree.children.end(),
86  [&newValue](const auto &item) { return !(newValue >= item.value); });
87 
88  auto newChild = tree_node<T>{std::move(newValue)};
89 
90  // move all smaller childs as grandchild to the new child
91  for (auto it = itToMoved; it != tree.children.end(); ++it)
92  {
93  newChild.children.emplace_back(std::move(*it));
94  }
95  tree.children.erase(itToMoved, tree.children.end());
96  tree.children.emplace_back(std::move(newChild));
97 
98  return;
99  }
100 
101  if (tree.value == zero)
102  {
103  tree.value = std::move(newValue);
104  }
105  else
106  {
107  tree.children.emplace_back(tree_node<T>{std::move(newValue)});
108  }
109 }
110 
111 
112 ML_UTILS_END_NAMESPACE
@ T
Definition: SoKeyGrabber.h:71
void insert_set_sorted(tree_node< T > &tree, T newValue, T zero={})
Definition: mlContainers.h:51
void flatten(const tree_node< T > &tree, std::vector< T > &flatten_elements)
Definition: mlContainers.h:33
std::vector< tree_node > children
Definition: mlContainers.h:27