-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathB-Tree.cpp
314 lines (281 loc) · 7.52 KB
/
B-Tree.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
#include <iostream>
using namespace std;
//Node protoType Functions
template<class T,int Order>
struct Node
{
//Node *Parent;
int number_of_keys;//number of the actual keys
int order;
int position=-1;//to allocate value in the appropriate place
T* keys;
Node** children;
explicit Node (int order);
int Insert (T value);
Node* split (Node* node, T* med);
void Print () ;
void PrintUtil (int height,bool checkRoot);
int getHeight () ;
~Node ();
};
/////////////////////////////////////////////////////////////
//Node implementation
template <class T,int Order>
Node<T,Order>::Node (int order)
{
this->order = order;
this->number_of_keys = 0;
// Allocate memory AFTER setting order
this->keys = new T[this->order];
this->children = new Node*[this->order + 1];
// Initialize children to NULL
for (int i = 0; i <= this->order; ++i)
this->children[i] = nullptr;
}
template <class T,int Order>
int Node<T,Order>::Insert (T value)
{
//if the node is leafed
if (this->children[0] == nullptr)
{
this->keys[++this->position] = value;
++this->number_of_keys;
//arrange the key array after put new value in node
for(int i=this->position; i>0 ; i--)
if (this->keys[i] < this->keys[i-1])
std::swap(this->keys[i],this->keys[i-1]);
}
//if the node is not leaf
else
{
//count to get place of child to put the value in it
int i=0;
for(; i<this->number_of_keys && value > this->keys[i];)
i++;
//Check if the child is full to split it
int check=this->children[i]->Insert(value);
//if node full
if(check)
{
T mid;
int TEMP = i;
Node<T,Order> *newNode = split(this->children[i], &mid); //Split Node
// to store the values and child that greater than the midValue
//allocate midValue the correct place
for(; i<this->number_of_keys && mid > this->keys[i];)
i++;
for (int j = this->number_of_keys; j > i ; j--)
this->keys[j] = this->keys[j - 1];
this->keys[i] = mid;
++this->number_of_keys;
++this->position;
//allocate newNode Split in the correct place
int k;
for (k = this->number_of_keys; k > TEMP + 1; k--)
this->children[k] = this->children[k - 1];
this->children[k] = newNode;
}
}
if(this->number_of_keys == this->order)
return 1;//to split it
else return 0;
}
template <class T,int Order>
Node<T,Order>* Node<T,Order>::split (Node *node, T *med) //mid to store value of mid and use it in insert func
{
int NumberOfKeys = node->number_of_keys;
auto *newNode = new Node<T,Order>(order);
//Node<T,Order> *newParentNode = new Node<T,Order>(order);
int midValue = NumberOfKeys / 2;
*med = node->keys[midValue];
int i;
//take the values after mid-value
for (i = midValue + 1; i < NumberOfKeys; ++i)
{
newNode->keys[++newNode->position] = node->keys[i];
newNode->children[newNode->position] = node->children[i];
++newNode->number_of_keys;
--node->position;
--node->number_of_keys;
node->children[i] = nullptr;
}
newNode->children[newNode->position + 1] = node->children[i];
node->children[i] = nullptr;
--node->number_of_keys; //because we take mid-value...
--node->position;
return newNode;
}
template <class T,int Order>
void Node<T,Order>::Print ()
{
int height = this->getHeight(); //number of levels -> log (n)
for (int i = 1; i <= height; ++i) //50 levels maximum
{
//O(n)
if(i==1)PrintUtil(i,true);
else PrintUtil(i,false);
cout<<endl;
}
cout<<endl;
}
template <class T,int Order>
void Node<T,Order>::PrintUtil (int height,bool checkRoot)
{
//to print all values in the level
if (height==1 || checkRoot)
{
for (int i = 0; i < this->number_of_keys; i++){
if(i==0) cout << "|";
cout<< this->keys[i];
if(i!=this->number_of_keys-1) cout<<"|";
if(i==this->number_of_keys-1) cout << "|"<<" ";
}
}
else
{
for (int i = 0; i <= this->number_of_keys; i++)
this->children[i]->PrintUtil(height - 1, false);
//cout<<endl<<" ";
}
}
template <class T,int Order>
int Node<T,Order>::getHeight ()
{
int COUNT=1;
Node<T,Order>* Current=this;//current point to root
while(true){
//is leafed
if(Current->children[0] == nullptr)
return COUNT;
Current=Current->children[0];
COUNT++;
}
}
// De-allocation
template <class T,int Order>
Node<T,Order>::~Node ()
{
delete[]keys;
// Only delete non-NULL child pointers
for (int i = 0; i <= this->number_of_keys; ++i)
delete children[i];
delete[] children;
}
/////////////////////////////////////////////////////////////
//BTree protoType Function
template <class T,int Order>
class BTree
{
private:
Node<T,Order> *root;
int order;
int count=0; //to count the number of elements
public:
BTree ();
void Insert (T value);
void Print () const;
~BTree ();
};
/////////////////////////////////////////////////////////////
//BTree implementation
template <class T,int Order>
BTree<T,Order>::BTree()
{
this->order = Order;
this->root = nullptr;
this->count=0;
}
template <class T,int Order>
void BTree<T,Order>::Insert (T value)
{
count++;
//if the Tree is empty
if (this->root == nullptr)
{
this->root = new Node<T,Order>(this->order);
this->root->keys[++this->root->position]=value;
this->root->number_of_keys=1;
}
//if a tree doesn't empty
else
{
int check=root->Insert(value);
if(check){
T mid;
Node<T,Order> *splitNode = this->root->split(this->root, &mid);
auto *newNode = new Node<T,Order>(this->order);
newNode->keys[++newNode->position]=mid;
newNode->number_of_keys=1;
newNode->children[0] = root;
newNode->children[1] = splitNode;
this->root = newNode;
}
}
}
template <class T,int Order>
void BTree<T,Order>::Print () const
{
if (root != nullptr)
root->Print();
else cout<<"The B-Tree is Empty"<<endl;
}
template <class T,int Order>
BTree<T,Order>::~BTree ()
{
delete root;
}
////////////////////////////////////////////////////////////
int main ()
{
// Construct a BTree of order 3, which stores int data
BTree<int,3> t1;
t1.Insert(1);
t1.Insert(5);
t1.Insert(0);
t1.Insert(4);
t1.Insert(3);
t1.Insert(2);
t1.Print(); // Should output the following on the screen:
/*
1,4
0
2,3
5
*/
// Construct a BTree of order 5, which stores char data
BTree<char,5> t;
// Look at the example in our lecture:
t.Insert('G');
t.Insert('I');
t.Insert('B');
t.Insert('J');
t.Insert('C');
t.Insert('A');
t.Insert('K');
t.Insert('E');
t.Insert('D');
t.Insert('S');
t.Insert('T');
t.Insert('R');
t.Insert('L');
t.Insert('F');
t.Insert('H');
t.Insert('M');
t.Insert('N');
t.Insert('P');
t.Insert('Q');
t.Print(); // Should output the following on the screen:
//t.traverse();
/*
K
C,G
A,B
D,E,F
H,I,J
N,R
L,M
P,Q
S,T
*/
return 0;
}