-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathb+tree.cpp
382 lines (332 loc) · 7.87 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
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
#include<iostream>
#include<vector>
#include<algorithm>
#include<math.h>
#include<queue>
#include <sstream>
#include <string>
#include <fstream>
#include <stdlib.h>
using namespace std;
#define MIN_VAL -1000000001;
int N=4; //size of each node (Max no. of keys)
struct node
{
bool leaf;
vector<int> records;
vector<int> count;
vector<node*> pointers;
node() //default node is not a leaf
{
leaf = false;
}
};
node* root;
void range(node* cur, int llimit,int rlimit)
{
if(cur->leaf)
{
//perform search in node
int total=0;
while(cur && cur->records[0] <= rlimit)
{
for(int i=0;i<cur->records.size();i++)
{
if(llimit <= cur->records[i] && cur->records[i] <= rlimit)
{
total += cur->count[i];
}
}
if(cur->pointers.empty())
break;
cur = cur->pointers[0];
}
cout<<total<<endl;
}
else
{
int i=0;
//find correct child node and recurse
for(i=0;i<cur->records.size();i++)
{
if(llimit < cur->records[i])
{
break;
}
}
range(cur->pointers[i],llimit,rlimit);
}
}
void count(node* cur, int key)
{
if(cur->leaf)
{
//perform search in node
for(int i=0;i<cur->records.size();i++)
{
if(key == cur->records[i])
{
cout<<cur->count[i]<<endl;
return;
}
}
cout<<0<<endl;
}
else
{
int i=0;
//find correct child node and recurse
for(i=0;i<cur->records.size();i++)
{
if(key < cur->records[i])
{
break;
}
}
count(cur->pointers[i],key);
}
}
void find(node* cur, int key)
{
if(cur->leaf)
{
//perform search in node
for(int i=0;i<cur->records.size();i++)
{
if(key == cur->records[i])
{
cout<<"YES"<<endl;
return;
}
}
cout<<"NO"<<endl;
}
else
{
int i=0;
//find correct child node and recurse
for(i=0;i<cur->records.size();i++)
{
if(key < cur->records[i])
{
break;
}
}
find(cur->pointers[i],key);
}
}
int insert_vec(node* tnode,int key)
{
int i=0;
for(i=0;i<tnode->records.size();i++)
{
if(key <= tnode->records[i])
break;
}
if(i<tnode->records.size() && key == tnode->records[i]) //Handle duplicate keys
{
tnode->count[i]++;
}
else
{
tnode->records.insert(tnode->records.begin()+i,key);
if(tnode->leaf)
tnode->count.insert(tnode->count.begin()+i,1);
}
return i;
}
void print_btree(queue<node*> printq) //debug purpose
{
if(printq.empty())
return;
queue<node*> newq;
while(!printq.empty())
{
for(int i=0;i<printq.front()->pointers.size();i++)
{
if(printq.front()->leaf)
break;
newq.push(printq.front()->pointers[i]);
}
if(!printq.front()->pointers.empty())
cout<<printq.front()<<" -- "<<printq.front()->pointers[0];
for(int i=0;i<printq.front()->records.size();i++) //TODO: Try using templates to print vector
{
if(printq.front()->leaf)
{
cout<<" @ "<<printq.front()->records[i];
}
else
{
cout<<" @ "<<printq.front()->records[i]<<" @ "<<printq.front()->pointers[i+1];
}
}
cout<<" ## ";
printq.pop();
}
cout<<endl;
cout<<endl;
print_btree(newq);
}
node* key_insert(node* cur,node* par,int val)
{
if(cur->leaf == true)
{
insert_vec(cur,val); //insert key
if(cur->records.size() > N) //split situation for leaf node
{
//cout<<"Leaf Node Overflow"<<endl;
node* rnode = new node(); //Create sibling on the right
rnode->leaf = true;
rnode->records.assign(cur->records.begin()+ceil((N+1)/2.0),cur->records.end()); //copy half elements from lnode to rnode
rnode->count.assign(cur->count.begin()+ceil((N+1)/2.0),cur->count.end()); //copy the counts for the same
cur->records.resize(ceil((N+1)/2.0)); //remove elements of rnode from lnode
cur->count.resize(ceil((N+1)/2.0)); //remove counts of rnode from lnode
//Create connection across leaves
rnode->pointers.resize(1);
cur->pointers.resize(1);
rnode->pointers[0] = cur->pointers[0];
cur->pointers[0] = rnode; //using 0th pointer element to connect leaves
if(cur == par) //root node is being split
{
node* rootnode = new node();
rootnode->pointers.push_back(cur);
rootnode->pointers.push_back(rnode);
rootnode->records.push_back(rnode->records[0]);
root = rootnode; //Updated to new root node
return NULL;
}
return rnode; //return entire rnode for parent to link
}
return NULL;
}
else
{
//records for a node CANNOT be empty. Avoiding check
int i=0;
while(i < cur->records.size() && val >= cur->records[i]) //Find the appropriate pointer
{
i++;
}
node* ret = key_insert(cur->pointers[i],cur,val); //Go down appropriate pointer to next child node
//Check if key returned and then insert to current inner node.
//ret->records[0] is the key that needs to be inserted in parent
if(ret != NULL) //Split had occurred in the node below
{
int pos = insert_vec(cur,ret->records[0]);
if(ret->leaf) //The node split below was a leaf node
{
cur->pointers.insert(cur->pointers.begin()+pos+1,ret); //+1 represents pointer to node greater than current key value
}
else //The node split below was a inner node.
{
cur->pointers.insert(cur->pointers.begin()+pos+1,ret->pointers[0]); //Different rnode as compared to leaf node
}
// Handle splitting of inner node.
if(cur->records.size() > N) //inner node is overflowing
{
//cout<<"Inner Node Overflow"<<endl;
node* rnode = new node();
int tkey = cur->records[ceil(N/2.0)];
rnode->records.assign(cur->records.begin()+ceil(N/2.0)+1,cur->records.end()); //copy half elements from lnode to rnode
rnode->pointers.assign(cur->pointers.begin()+ceil((N+2)/2.0),cur->pointers.end()); //copy the pointers for the same
cur->records.resize(ceil(N/2.0)); //remove elements of rnode from lnode
cur->pointers.resize(ceil((N+2)/2.0)); //remove pointers of rnode from lnode
if(cur == par) //root node is being split
{
node* rootnode = new node();
rootnode->pointers.push_back(cur);
rootnode->pointers.push_back(rnode);
rootnode->records.push_back(tkey);
root = rootnode; //Updated to new root node
return NULL;
}
//TODO: return a node with middle key and pointer to rnode
node* retnode = new node();
retnode->records.push_back(tkey);
retnode->pointers.push_back(rnode);
return retnode;
}
}
}
}
void print_assist()
{
queue<node*> tnode;
tnode.push(root);
cout<<"Printing B+tree"<<endl;
print_btree(tnode);
}
int main(int argc,char *argv[])
{
cout<<"B+Tree Program"<<endl;
root = new node();
root->leaf = true;
ifstream infile(argv[1]);
string line,c;
int a,b=-1;
while (getline(infile, line))
{
istringstream iss(line);
iss>>c>>a>>b;
if(line[0] == 'I')
{
key_insert(root,root,a);
}
else if(line[0] == 'F')
{
find(root,a);
}
else if(line[0] == 'C')
{
count(root,a);
}
else if(line[0] == 'R')
{
range(root,a,b);
}
else if(line[0] == 'P')
{
print_assist();
}
else
{
cout<<"Input format error"<<endl;
}
}
/*
//Test Code
key_insert(root,root,5);
key_insert(root,root,3);
key_insert(root,root,2);
key_insert(root,root,4);
print_assist();
key_insert(root,root,6);
key_insert(root,root,7);
key_insert(root,root,1);
key_insert(root,root,0);
key_insert(root,root,5);
print_assist();
key_insert(root,root,8);
key_insert(root,root,-1);
key_insert(root,root,-2);
key_insert(root,root,2);
key_insert(root,root,2);
print_assist();
key_insert(root,root,-3);
key_insert(root,root,-4);
key_insert(root,root,-5);
key_insert(root,root,-6);
print_assist();
key_insert(root,root,9);
find(root,0);
find(root,7);
find(root,-14);
count(root,2);
count(root,-11);
count(root,4);
range(root,0,4);
range(root,53,68);
range(root,6,12);
*/
}