restructure and add ipi texs

This commit is contained in:
2019-11-06 18:24:04 +01:00
parent e21da561fc
commit 8fd8d2a485
155 changed files with 129 additions and 0 deletions
+179
View File
@@ -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);
}