restructure and add ipi texs
This commit is contained in:
@@ -0,0 +1,179 @@
|
||||
#include<set>
|
||||
#include<iostream>
|
||||
#include<vector>
|
||||
#include<cassert>
|
||||
using namespace std;
|
||||
|
||||
const int m = 2; // B-tree of order m
|
||||
const int a = m; // minimal number of keys
|
||||
const int b = 2*m; // maximal number of keys
|
||||
|
||||
template<class T>
|
||||
struct Node {
|
||||
// data
|
||||
vector<T> keys;
|
||||
vector<Node *> children;
|
||||
Node* parent;
|
||||
// interface
|
||||
Node (Node* p) {parent = p;}
|
||||
bool is_leaf() {return children.size()==0;}
|
||||
Node* root () { return (parent==0) ? this : parent->root(); }
|
||||
Node* find_node (T item);
|
||||
int find_pos (T item);
|
||||
bool equals_item (int pos, T item);
|
||||
} ;
|
||||
|
||||
// finds first position i such that keys[i]>=item
|
||||
template<class T>
|
||||
int Node<T>::find_pos (T item)
|
||||
{
|
||||
int i = 0;
|
||||
while ((i<keys.size())&&(keys[i]<item)) i++;
|
||||
return i;
|
||||
}
|
||||
|
||||
// checks if the key at position pos contains item
|
||||
template<class T>
|
||||
bool Node<T>::equals_item (int pos, T item) {
|
||||
return (pos<keys.size()) && !(item<keys[pos]);
|
||||
}
|
||||
|
||||
// finds the node in which the item should be stored
|
||||
template<class T>
|
||||
Node<T>* Node<T>::find_node (T item) {
|
||||
if (is_leaf()) return this;
|
||||
int pos = find_pos(item);
|
||||
if (equals_item(pos, item))
|
||||
return this;
|
||||
else
|
||||
return children[pos]->find_node(item);
|
||||
}
|
||||
|
||||
template<class VEC>
|
||||
VEC subseq (VEC vec, int start, int end)
|
||||
{
|
||||
int size = (vec.size()==0) ? 0 : end-start;
|
||||
VEC result(size);
|
||||
for (int i = 0; i<size; i++)
|
||||
result[i] = vec[i+start];
|
||||
return result;
|
||||
}
|
||||
|
||||
// if necessary, split the node. Returns 0 or a new root
|
||||
template<class T>
|
||||
Node<T>* balance (Node<T>* node)
|
||||
{
|
||||
int n = node->keys.size();
|
||||
if (n<=b) return 0;
|
||||
T median = node->keys[a];
|
||||
// create a new node
|
||||
Node<T>* node2 = new Node<T>(node->parent);
|
||||
node2->keys = subseq(node->keys, a+1,
|
||||
node->keys.size());
|
||||
node2->children = subseq(node->children, a+1,
|
||||
node->children.size());
|
||||
for (int i=0; i<node2->children.size(); i++)
|
||||
node2->children[i]->parent = node2;
|
||||
// handle node
|
||||
node->keys = subseq(node->keys, 0, a);
|
||||
node->children = subseq(node->children, 0, a+1);
|
||||
|
||||
Node<T>* parent = node->parent;
|
||||
if (parent==0) // split the root!
|
||||
{
|
||||
Node<T>* root = new Node<T>(0);
|
||||
root->keys.push_back(median);
|
||||
root->children.push_back(node);
|
||||
root->children.push_back(node2);
|
||||
node->parent = root;
|
||||
node2->parent = root;
|
||||
return root;
|
||||
}
|
||||
// otherwise: insert in parent
|
||||
int pos=0;
|
||||
while (parent->children[pos]!=node) pos++;
|
||||
parent->keys.insert(parent->keys.begin()+pos, median);
|
||||
parent->children.insert(parent->children.begin()+pos+1, node2);
|
||||
// recursive call;
|
||||
return balance(parent);
|
||||
}
|
||||
|
||||
template<class T>
|
||||
void show (Node<T> *node)
|
||||
{
|
||||
cout << node << ": ";
|
||||
if (node->children.size()>0)
|
||||
{
|
||||
cout << node->children[0];
|
||||
for (int i=0; i<node->keys.size(); i++)
|
||||
cout << " |" << node->keys[i] << "| "
|
||||
<< node->children[i+1];
|
||||
}
|
||||
else
|
||||
for (int i=0; i<node->keys.size(); i++)
|
||||
cout << node->keys[i] << " ";
|
||||
cout << endl;
|
||||
for (int i=0; i<node->children.size(); i++)
|
||||
show(node->children[i]);
|
||||
}
|
||||
|
||||
// we could work with a root pointer, but for later use it is
|
||||
// better to wrap it into a class
|
||||
|
||||
template<class T>
|
||||
class abTree {
|
||||
public:
|
||||
abTree () {root = new Node<T>(0);}
|
||||
void insert (T item);
|
||||
bool find (T item);
|
||||
void show () { ::show(root); }
|
||||
private:
|
||||
Node<T> *root;
|
||||
};
|
||||
|
||||
template<class T>
|
||||
void abTree<T>::insert (T item) {
|
||||
Node<T>* node = root->find_node(item);
|
||||
int i=node->find_pos(item);
|
||||
if (node->equals_item(i,item))
|
||||
node->keys[i] = item;
|
||||
else
|
||||
{
|
||||
node->keys.insert(node->keys.begin()+i, item);
|
||||
Node<T>* new_root = balance(node);
|
||||
if (new_root) root = new_root;
|
||||
}
|
||||
}
|
||||
|
||||
template<class T>
|
||||
bool abTree<T>::find (T item) {
|
||||
Node<T>* node = root->find_node(item);
|
||||
int i=node->find_pos(item);
|
||||
return node->equals_item(i, item);
|
||||
}
|
||||
|
||||
int main ()
|
||||
{
|
||||
abTree<int> tree;
|
||||
// insertion demo
|
||||
for (int i=0; i<5; i++) {
|
||||
tree.insert(i);
|
||||
tree.show();
|
||||
}
|
||||
// testing insertion and retrieval
|
||||
int n = 10;
|
||||
for (int i=0; i<n; i++)
|
||||
tree.insert(i*i);
|
||||
cout << endl;
|
||||
tree.show();
|
||||
for (int i=0; i<2*n; i++)
|
||||
cout << i << " " << tree.find(i) << endl;
|
||||
// performance test
|
||||
//abTree<int> set;
|
||||
set<int> set; // should be faster
|
||||
int nn = 1000000;
|
||||
for (int i=0; i<nn; i++)
|
||||
set.insert(i*i);
|
||||
for (int i=0; i<nn; i++)
|
||||
set.find(i*i);
|
||||
}
|
||||
Reference in New Issue
Block a user