ML 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
19ML_UTILS_START_NAMESPACE
20
21/*
22 * A structure that implements a value based tree
23 */
24template <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 */
33template <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 */
50template <typename T>
51void 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
112ML_UTILS_END_NAMESPACE
void insert_set_sorted(tree_node< T > &tree, T newValue, T zero={})
void flatten(const tree_node< T > &tree, std::vector< T > &flatten_elements)
std::vector< tree_node > children