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:
21 BPlusTree(int maxKeys);
22
29 bool insert(TKey key, TValue* value);
30
36 bool remove(TKey key);
37
43 TValue* search(TKey key);
44 private:
45 Node<TKey, TValue>* _root;
46 int _keysMax;
47
54 void splitChild(Node<TKey, TValue>* parent, int index, Node<TKey, TValue>* child);
55
62 void insertNonFull(Node<TKey, TValue>* node, TKey key, TValue* value);
63
69 void remove(Node<TKey, TValue>* node, TKey key);
70
76 void merge(Node<TKey, TValue>* node, int index);
77
83 void borrowFromPrev(Node<TKey, TValue>* node, int index);
84
90 void borrowFromNext(Node<TKey, TValue>* node, int index);
91 };
92
93 template <typename TKey, typename TValue>
95 _root(nullptr),
96 _keysMax(maxKeys)
97 {}
98
99 template <typename TKey, typename TValue>
100 bool BPlusTree<TKey, TValue>::insert(TKey key, TValue* value)
101 {
102 if (_root == nullptr)
103 {
104 _root = new Node<TKey, TValue>(true);
105 _root->keys.push_back(key);
106 _root->values.push_back(*value);
107 return true;
108 }
109 else {
110 if (_root->keys.size() == 2 * _keysMax - 1)
111 {
112 Node<TKey, TValue>* newRoot = new Node<TKey, TValue>(false);
113 newRoot->children.push_back(_root);
114 splitChild(newRoot, 0, _root);
115 _root = newRoot;
116 }
117 insertNonFull(_root, key, value);
118 return true;
119 }
120 }
121
122 template <typename TKey, typename TValue>
124 {
125 if (_root == nullptr) {
126 return false;
127 }
128 remove(_root, key);
129 if (_root->keys.empty() && !_root->isLeaf) {
130 Node<TKey, TValue>* tmp = _root;
131 _root = _root->children[0];
132 delete tmp;
133 return true;
134 }
135 return false;
136 }
137
138 template <typename TKey, typename TValue>
140 {
141
142 if (!_root)
143 return nullptr;
144
145 Node<TKey, TValue>* current = _root;
146
147 while (!current->isLeaf)
148 {
149 size_t i = 0;
150 while (i < current->keys.size() && key >= current->keys[i])
151 ++i;
152 current = current->children[i];
153 }
154
155 for (size_t i = 0; i < current->keys.size(); ++i)
156 {
157 if (current->keys[i] == key)
158 return &current->values[i];
159 }
160
161 return nullptr;
162 }
163
164 template <typename TKey, typename TValue>
165 void BPlusTree<TKey, TValue>::splitChild(
166 Node<TKey, TValue>* parent,
167 int index,
168 Node<TKey, TValue>* child)
169 {
170 Node<TKey, TValue>* newChild = new Node<TKey, TValue>(child->isLeaf);
171
172 parent->children.insert(
173 parent->children.begin() + index + 1,
174 newChild);
175
176 parent->keys.insert(
177 parent->keys.begin() + index,
178 child->keys[_keysMax - 1]);
179
180 newChild->keys.assign(
181 child->keys.begin() + _keysMax,
182 child->keys.end());
183
184 child->keys.resize(_keysMax - 1);
185
186 if (!child->isLeaf)
187 {
188 newChild->children.assign(
189 child->children.begin() + _keysMax,
190 child->children.end());
191 child->children.resize(_keysMax);
192 }
193
194 if (child->isLeaf)
195 {
196 newChild->next = child->next;
197 child->next = newChild;
198 }
199 }
200
201 template <typename TKey, typename TValue>
202 void BPlusTree<TKey, TValue>::insertNonFull(
203 Node<TKey, TValue>* node,
204 TKey key,
205 TValue* value)
206 {
207 if (node->isLeaf)
208 {
209 auto pos = std::upper_bound(
210 node->keys.begin(),
211 node->keys.end(),
212 key);
213 size_t index = std::distance(node->keys.begin(), pos);
214 node->keys.insert(pos, key);
215 node->values.insert(node->values.begin() + index, *value);
216 }
217 else
218 {
219 int i = node->keys.size() - 1;
220
221 while (i >= 0 && key < node->keys[i])
222 i--;
223
224 i++;
225
226 if (node->children[i]->keys.size() == 2 * _keysMax - 1)
227 {
228 splitChild(node, i, node->children[i]);
229
230 if (key > node->keys[i])
231 i++;
232 }
233
234 insertNonFull(node->children[i], key, value);
235 }
236 }
237
238 template <typename TKey, typename TValue>
240 Node<TKey, TValue>* node,
241 TKey key)
242 {
243 if (node->isLeaf)
244 {
245 auto it = std::find(
246 node->keys.begin(),
247 node->keys.end(),
248 key);
249
250 if (it != node->keys.end())
251 {
252 size_t index = std::distance(node->keys.begin(), it);
253 node->keys.erase(it);
254 node->values.erase(node->values.begin() + index);
255 }
256 }
257 else
258 {
259 int index = std::distance(
260 node->keys.begin(),
261 std::lower_bound(
262 node->keys.begin(),
263 node->keys.end(),
264 key));
265
266 if (index < node->keys.size() && node->keys[index] == key)
267 {
268 if (node->children[index]->keys.size() >= _keysMax)
269 {
270 Node<TKey, TValue>* predecessorNode = node->children[index];
271 while (!predecessorNode->isLeaf)
272 predecessorNode = predecessorNode->children.back();
273
274 TKey predecessorKey = predecessorNode->keys.back();
275 TValue predecessorVal = predecessorNode->values.back();
276 node->keys[index] = predecessorKey;
277 node->values[index] = predecessorVal;
278
279 remove(node->children[index], predecessorKey);
280 }
281 else if (node->children[index + 1]->keys.size() >= _keysMax)
282 {
283 Node<TKey, TValue>* successorNode = node->children[index + 1];
284 while(!successorNode->isLeaf)
285 successorNode = successorNode->children.front();
286
287 TKey successorKey = successorNode->keys.front();
288 TValue successorVal = successorNode->values.front();
289 node->keys[index] = successorKey;
290 node->values[index] = successorVal;
291
292 remove(node->children[index + 1], successorKey);
293 }
294 else
295 {
296 merge(node, index);
297 remove(node->children[index], key);
298 }
299 }
300 else
301 {
302 if (node->children[index]->keys.size() < _keysMax)
303 {
304 if (index > 0 &&
305 node->children[index - 1]->keys.size() >= _keysMax)
306 borrowFromPrev(node, index);
307 else if (index < node->children.size() - 1 &&
308 node->children[index + 1]->keys.size() >= _keysMax)
309 borrowFromNext(node, index);
310 else
311 {
312 if (index < node->children.size() -1)
313 merge(node, index);
314 else
315 merge(node, index - 1);
316 }
317 }
318 remove(node->children[index], key);
319 }
320 }
321 }
322
323 template <typename TKey, typename TValue>
324 void BPlusTree<TKey, TValue>::merge(
325 Node<TKey, TValue>* node,
326 int index)
327 {
328 Node<TKey, TValue>* child = node->children[index];
329 Node<TKey, TValue>* sibling = node->children[index + 1];
330
331 child->keys.push_back(node->keys[index]);
332 child->values.push_back(node->values[index]);
333
334 child->keys.insert(
335 child->keys.end(),
336 sibling->keys.begin(),
337 sibling->keys.end());
338 child->values.insert(
339 child->values.end(),
340 sibling->values.begin(),
341 sibling->values.end());
342
343 if (!child->isLeaf)
344 {
345 child->children.insert(child->children.end(),
346 sibling->children.begin(),
347 sibling->children.end());
348 }
349
350 node->keys.erase(node->keys.begin() + index);
351 node->values.erase(node->values.begin() + index);
352 node->children.erase(node->children.begin() + index + 1);
353
354 delete sibling;
355 }
356
357 template <typename TKey, typename TValue>
358 void BPlusTree<TKey, TValue>::borrowFromPrev(
359 Node<TKey, TValue>* node,
360 int index)
361 {
362 Node<TKey, TValue>* child = node->children[index];
363 Node<TKey, TValue>* sibling = node->children[index - 1];
364
365 child->keys.insert(child->keys.begin(), node->keys[index - 1]);
366 child->values.insert(child->values.begin(), node->values[index - 1]);
367
368 node->keys[index - 1] = sibling->keys.back();
369 node->values[index - 1] = sibling->values.back();
370
371 sibling->keys.pop_back();
372 sibling->values.pop_back();
373
374 if (!child->isLeaf) {
375 child->children.insert(child->children.begin(), sibling->children.back());
376 sibling->children.pop_back();
377 }
378 }
379
380 template <typename TKey, typename TValue>
381 void BPlusTree<TKey, TValue>::borrowFromNext(
382 Node<TKey, TValue>* node,
383 int index)
384 {
385 Node<TKey, TValue>* child = node->children[index];
386 Node<TKey, TValue>* sibling = node->children[index + 1];
387
388 child->keys.push_back(node->keys[index]);
389 child->values.push_back(node->values[index]);
390
391 node->keys[index] = sibling->keys.front();
392 node->values[index] = sibling->values.front();
393
394 sibling->keys.erase(sibling->keys.begin());
395 sibling->values.erase(sibling->values.begin());
396
397 if (!child->isLeaf) {
398 child->children.push_back(sibling->children.front());
399 sibling->children.erase(sibling->children.begin());
400 }
401 }
402}
403
404#endif // DATA_STRUCTURE_PLUS_BTREE_H
bool remove(TKey key)
Remove a key from the B+ Tree.
Definition BPlusTree.h:123
TValue * search(TKey key)
Search for a key in the B+ Tree.
Definition BPlusTree.h:139
BPlusTree(int maxKeys)
Constructor.
Definition BPlusTree.h:94
bool insert(TKey key, TValue *value)
Insert a key-value pair into the B+ Tree.
Definition BPlusTree.h:100
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