xale-db 1.0
minimal SQL engine, written in c++
Loading...
Searching...
No Matches
BPlusTree.h
Go to the documentation of this file.
1#ifndef DATA_STRUCTURE_PLUS_BTREE_H
2#define DATA_STRUCTURE_PLUS_BTREE_H
3
5
6#include <algorithm>
7
9{
13 template <typename TKey, typename TValue>
15 {
16 public:
17 BPlusTree(int maxKeys);
18 bool insert(TKey key, TValue* value);
19 bool remove(TKey key);
20 TValue* search(TKey key);
21 private:
22 Node<TKey, TValue>* _root;
23 int _keysMax;
24
25 void splitChild(Node<TKey, TValue>* parent, int index, Node<TKey, TValue>* child);
26 void insertNonFull(Node<TKey, TValue>* node, TKey key, TValue* value);
27 void remove(Node<TKey, TValue>* node, TKey key);
28 void merge(Node<TKey, TValue>* node, int index);
29 void borrowFromPrev(Node<TKey, TValue>* node, int index);
30 void borrowFromNext(Node<TKey, TValue>* node, int index);
31 };
32
37 template <typename TKey, typename TValue>
39 _root(nullptr),
40 _keysMax(maxKeys)
41 {}
42
49 template <typename TKey, typename TValue>
50 bool BPlusTree<TKey, TValue>::insert(TKey key, TValue* value)
51 {
52 if (_root == nullptr)
53 {
54 _root = new Node<TKey, TValue>(true);
55 _root->keys.push_back(key);
56 _root->values.push_back(*value);
57 return true;
58 }
59 else {
60 if (_root->keys.size() == 2 * _keysMax - 1)
61 {
62 Node<TKey, TValue>* newRoot = new Node<TKey, TValue>(false);
63 newRoot->children.push_back(_root);
64 splitChild(newRoot, 0, _root);
65 _root = newRoot;
66 }
67 insertNonFull(_root, key, value);
68 return true;
69 }
70 }
71
77 template <typename TKey, typename TValue>
79 {
80 if (_root == nullptr) {
81 return false;
82 }
83 remove(_root, key);
84 if (_root->keys.empty() && !_root->isLeaf) {
85 Node<TKey, TValue>* tmp = _root;
86 _root = _root->children[0];
87 delete tmp;
88 return true;
89 }
90 return false;
91 }
92
98 template <typename TKey, typename TValue>
100 {
101
102 if (!_root)
103 return nullptr;
104
105 Node<TKey, TValue>* current = _root;
106
107 while (!current->isLeaf)
108 {
109 size_t i = 0;
110 while (i < current->keys.size() && key >= current->keys[i])
111 ++i;
112 current = current->children[i];
113 }
114
115 for (size_t i = 0; i < current->keys.size(); ++i)
116 {
117 if (current->keys[i] == key)
118 return &current->values[i];
119 }
120
121 return nullptr;
122 }
123
124 template <typename TKey, typename TValue>
125 void BPlusTree<TKey, TValue>::splitChild(
126 Node<TKey, TValue>* parent,
127 int index,
128 Node<TKey, TValue>* child)
129 {
130 Node<TKey, TValue>* newChild = new Node<TKey, TValue>(child->isLeaf);
131
132 parent->children.insert(
133 parent->children.begin() + index + 1,
134 newChild);
135
136 parent->keys.insert(
137 parent->keys.begin() + index,
138 child->keys[_keysMax - 1]);
139
140 newChild->keys.assign(
141 child->keys.begin() + _keysMax,
142 child->keys.end());
143
144 child->keys.resize(_keysMax - 1);
145
146 if (!child->isLeaf)
147 {
148 newChild->children.assign(
149 child->children.begin() + _keysMax,
150 child->children.end());
151 child->children.resize(_keysMax);
152 }
153
154 if (child->isLeaf)
155 {
156 newChild->next = child->next;
157 child->next = newChild;
158 }
159 }
160
161 template <typename TKey, typename TValue>
162 void BPlusTree<TKey, TValue>::insertNonFull(
163 Node<TKey, TValue>* node,
164 TKey key,
165 TValue* value)
166 {
167 if (node->isLeaf)
168 {
169 auto pos = std::upper_bound(
170 node->keys.begin(),
171 node->keys.end(),
172 key);
173 size_t index = std::distance(node->keys.begin(), pos);
174 node->keys.insert(pos, key);
175 node->values.insert(node->values.begin() + index, *value);
176 }
177 else
178 {
179 int i = node->keys.size() - 1;
180
181 while (i >= 0 && key < node->keys[i])
182 i--;
183
184 i++;
185
186 if (node->children[i]->keys.size() == 2 * _keysMax - 1)
187 {
188 splitChild(node, i, node->children[i]);
189
190 if (key > node->keys[i])
191 i++;
192 }
193
194 insertNonFull(node->children[i], key, value);
195 }
196 }
197
198 template <typename TKey, typename TValue>
200 Node<TKey, TValue>* node,
201 TKey key)
202 {
203 if (node->isLeaf)
204 {
205 auto it = std::find(
206 node->keys.begin(),
207 node->keys.end(),
208 key);
209
210 if (it != node->keys.end())
211 {
212 size_t index = std::distance(node->keys.begin(), it);
213 node->keys.erase(it);
214 node->values.erase(node->values.begin() + index);
215 }
216 }
217 else
218 {
219 int index = std::distance(
220 node->keys.begin(),
221 std::lower_bound(
222 node->keys.begin(),
223 node->keys.end(),
224 key));
225
226 if (index < node->keys.size() && node->keys[index] == key)
227 {
228 if (node->children[index]->keys.size() >= _keysMax)
229 {
230 Node<TKey, TValue>* predecessorNode = node->children[index];
231 while (!predecessorNode->isLeaf)
232 predecessorNode = predecessorNode->children.back();
233
234 TKey predecessorKey = predecessorNode->keys.back();
235 TValue predecessorVal = predecessorNode->values.back();
236 node->keys[index] = predecessorKey;
237 node->values[index] = predecessorVal;
238
239 remove(node->children[index], predecessorKey);
240 }
241 else if (node->children[index + 1]->keys.size() >= _keysMax)
242 {
243 Node<TKey, TValue>* successorNode = node->children[index + 1];
244 while(!successorNode->isLeaf)
245 successorNode = successorNode->children.front();
246
247 TKey successorKey = successorNode->keys.front();
248 TValue successorVal = successorNode->values.front();
249 node->keys[index] = successorKey;
250 node->values[index] = successorVal;
251
252 remove(node->children[index + 1], successorKey);
253 }
254 else
255 {
256 merge(node, index);
257 remove(node->children[index], key);
258 }
259 }
260 else
261 {
262 if (node->children[index]->keys.size() < _keysMax)
263 {
264 if (index > 0 &&
265 node->children[index - 1]->keys.size() >= _keysMax)
266 borrowFromPrev(node, index);
267 else if (index < node->children.size() - 1 &&
268 node->children[index + 1]->keys.size() >= _keysMax)
269 borrowFromNext(node, index);
270 else
271 {
272 if (index < node->children.size() -1)
273 merge(node, index);
274 else
275 merge(node, index - 1);
276 }
277 }
278 remove(node->children[index], key);
279 }
280 }
281 }
282
283 template <typename TKey, typename TValue>
284 void BPlusTree<TKey, TValue>::merge(
285 Node<TKey, TValue>* node,
286 int index)
287 {
288 Node<TKey, TValue>* child = node->children[index];
289 Node<TKey, TValue>* sibling = node->children[index + 1];
290
291 child->keys.push_back(node->keys[index]);
292 child->values.push_back(node->values[index]);
293
294 child->keys.insert(
295 child->keys.end(),
296 sibling->keys.begin(),
297 sibling->keys.end());
298 child->values.insert(
299 child->values.end(),
300 sibling->values.begin(),
301 sibling->values.end());
302
303 if (!child->isLeaf)
304 {
305 child->children.insert(child->children.end(),
306 sibling->children.begin(),
307 sibling->children.end());
308 }
309
310 node->keys.erase(node->keys.begin() + index);
311 node->values.erase(node->values.begin() + index);
312 node->children.erase(node->children.begin() + index + 1);
313
314 delete sibling;
315 }
316
317 template <typename TKey, typename TValue>
318 void BPlusTree<TKey, TValue>::borrowFromPrev(
319 Node<TKey, TValue>* node,
320 int index)
321 {
322 Node<TKey, TValue>* child = node->children[index];
323 Node<TKey, TValue>* sibling = node->children[index - 1];
324
325 child->keys.insert(child->keys.begin(), node->keys[index - 1]);
326 child->values.insert(child->values.begin(), node->values[index - 1]);
327
328 node->keys[index - 1] = sibling->keys.back();
329 node->values[index - 1] = sibling->values.back();
330
331 sibling->keys.pop_back();
332 sibling->values.pop_back();
333
334 if (!child->isLeaf) {
335 child->children.insert(child->children.begin(), sibling->children.back());
336 sibling->children.pop_back();
337 }
338 }
339
340 template <typename TKey, typename TValue>
341 void BPlusTree<TKey, TValue>::borrowFromNext(
342 Node<TKey, TValue>* node,
343 int index)
344 {
345 Node<TKey, TValue>* child = node->children[index];
346 Node<TKey, TValue>* sibling = node->children[index + 1];
347
348 child->keys.push_back(node->keys[index]);
349 child->values.push_back(node->values[index]);
350
351 node->keys[index] = sibling->keys.front();
352 node->values[index] = sibling->values.front();
353
354 sibling->keys.erase(sibling->keys.begin());
355 sibling->values.erase(sibling->values.begin());
356
357 if (!child->isLeaf) {
358 child->children.push_back(sibling->children.front());
359 sibling->children.erase(sibling->children.begin());
360 }
361 }
362}
363
364#endif // DATA_STRUCTURE_PLUS_BTREE_H
bool remove(TKey key)
Remove a key from the B+ Tree.
Definition BPlusTree.h:78
TValue * search(TKey key)
Search for a key in the B+ Tree.
Definition BPlusTree.h:99
BPlusTree(int maxKeys)
B+Tree constructor.
Definition BPlusTree.h:38
bool insert(TKey key, TValue *value)
Insert a key-value pair into the B+ Tree.
Definition BPlusTree.h:50
Definition BPlusTree.h:9
Node struct for B+Tree implementation.
Definition Node.h:16
Node * next
Definition Node.h:23
std::vector< Node * > children
Definition Node.h:21
bool isLeaf
Definition Node.h:24
std::vector< TValue > values
Definition Node.h:20
std::vector< TKey > keys
Definition Node.h:19