Files
secondo/include/MMMTree.h
2026-01-23 17:03:45 +08:00

1379 lines
29 KiB
C++

/*
----
This file is part of SECONDO.
Copyright (C) 2004, University in Hagen, Department of Computer Science,
Database Systems for New Applications.
SECONDO is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
SECONDO is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with SECONDO; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
----
*/
#ifndef MMMTREE_H
#define MMMTREE_H
#include <assert.h>
#include <cstdlib>
#include <utility>
#include <iostream>
#include <stack>
#include <queue>
// implementation of a main memory based M-tree
/*
1 class MTreeNode
The class MTreeNode is an abstract super class for the nodes
of an m-tree.
*/
template<class T, class DistComp>
class MTreeNode{
public:
typedef MTreeNode<T,DistComp> node_t;
/*
1.1 Destructor
Destroy the subtree rooted by this node
*/
virtual ~MTreeNode(){}
/*
1.2 Methods
~isLeaf~
This function returns true if this node represents a leaf.
*/
virtual bool isLeaf() const = 0;
/*
~memSize~
Returns the amount of memory occupied by the subtree represented by this node.
*/
virtual size_t memSize() const = 0;
/*
1.3 ~getRoutingObject~
This funtion returns the routingObject (center) of a node.
*/
const T* getRoutingObject() const {
return &routingObject;
}
/*
~getRadius~
Returns the radius of this node.
*/
inline double getRadius() const{
return radius;
}
/*
~getMinEntries~
Return the minimum number of entries of this node.
*/
inline int getMinEntries() const{
return minEntries;
}
/*
~getMaxEntries~
Returns the capacity of this node.
*/
inline int getMaxEntries() const{
return maxEntries;
}
/*
~isOverflow~
Returns true if the node has more entries than allowed.
Note that a node temporarly can hold one node more than
the limit. In this case, the node must be splitted.
*/
inline bool isOverflow() const{
return count == maxEntries;
}
/*
~incraseRadius~
Increases the radius of this node in that way to include the
argument objects.
*/
inline void increaseRadius(const T& o, DistComp& dc){
double d = dc(routingObject,o);
if(d>radius){
radius = d;
}
}
/*
~getCount~
Returns the number of entries (sons or objects) of this node.
*/
inline int getCount() const{
return count;
}
/*
~centerDist~
Returns the distance between the routing object of this node and the
argument.
*/
inline double centerDist(const T& o, DistComp& di) const{
return di(routingObject,o);
}
/*
~minDist~
Returns the distance between the area repreented by this node and __o__.
If __o__ is inside the circle, 0 is returned.
*/
inline double minDist(const T& o, DistComp& di){
double dist = di(routingObject,o) - radius;
return dist>=0?dist:0;
}
/*
~getParent~
Returns the parent of this node or 0 if this node is the root of the tree.
*/
inline node_t* getParent(){
return parent;
}
/*
~setParent~
Sets the father node.
*/
inline void setParent(node_t* p, DistComp& di){
parent = p;
distanceToParent = distance(p, di);
}
/*
~distance~
Returns the distance between the routing objects of this node and
the routing objectt of the other one.
*/
inline double distance(node_t* node, DistComp& di) const{
return di(routingObject,node->routingObject);
}
/*
~clear~
Removes the entries from this node. If deleteContent is set to be
true, the sons of this node are destroyed.
*/
virtual void clear(const bool deleteContent) =0;
/*
~print~
Writes a textual representation of this node to ~out~.
*/
virtual std::ostream& print(std::ostream& out, DistComp& di) const = 0;
virtual std::ostream& print(std::ostream& out,
const bool printSubTrees,
DistComp& di) const =0;
/*
~getNoEntries~
Returns the number of entries stored in the tree rooted by this node.
*/
virtual int getNoEntries() const = 0;
/*
~getNoLeafs~
Returns the number of leafs within this subtree.
*/
virtual int getNoLeafs() const = 0;
/*
~getNoNodes~
Returns, how many nodes are within the subtree rooted by this.
*/
virtual int getNoNodes() const = 0;
virtual node_t* clone() = 0;
void setParent(node_t* p){
parent = p;
}
protected:
/*
1.3 Constructor
This constructor initializes all members
*/
MTreeNode(const T& Or, double rad, double dist,
const int _minEntries, const int _maxEntries):
routingObject(Or), radius(rad), distanceToParent(dist),
minEntries(_minEntries), maxEntries(_maxEntries), parent(0),count(0){}
/*
1.4 Member variables
*/
T routingObject;
double radius;
double distanceToParent;
int minEntries;
int maxEntries;
node_t* parent;
int count;
};
/*
2 Class ~MTreeInnerNode~
This class represents an inner node of an m-tree.
*/
template<class T,class DistComp>
class MTreeInnerNode: public MTreeNode<T,DistComp>{
public:
typedef MTreeInnerNode<T,DistComp> innernode_t;
typedef MTreeNode<T,DistComp> node_t;
/*
2.1 Constructor
This constructor creates a new inner node of an m-tree able to to __maxEntries__
sons. The routing object is given by ~Or~.
*/
MTreeInnerNode(const int _minEntries, const int _maxEntries, const T Or):
node_t(Or,0,0,_minEntries,_maxEntries)
{
sons = new node_t*[_maxEntries+1];
for(int i=0;i<_maxEntries+1;i++){
sons[i]=0;
}
}
/*
2.2 Destructor
Destroys the tree rooted by this node.
*/
virtual ~MTreeInnerNode(){
for(int i=0;i<node_t::maxEntries+1;i++){
if(sons[i]){
delete sons[i];
}
}
delete[] sons;
}
/*
2.3 Methods
~clear~
Removes all subtress from this node. If ~deleteContent~ is true,
all subtrees are destroyed.
*/
virtual void clear(const bool deleteContent){
for(int i=0;i<node_t::count;i++){
if(deleteContent){
delete sons[i];
}
sons[i] = 0;
}
node_t::count = 0;
}
/*
~isLeaf~
Implements the pure virtual function of the super class by
returning false.
*/
virtual bool isLeaf() const{
return false;
}
/*
~getBestSon~
returns the son of this node which is the best for
inserting o
*/
node_t* getBestSon(const T& o, DistComp& di) const{
node_t* res = 0;
double currentDist=0;
node_t* secondRes = 0;
double secondDist=0;
for(int i=0;i<node_t::count;i++){
const T* ro = (sons[i])->getRoutingObject();
double dist = di(o,*ro);
if(dist < sons[i]->getRadius()){ // o fits into the circle of son
if(!res || dist < currentDist){ // first fitting son
res = sons[i];
currentDist = dist;
}
}
if(!res){
if(!secondRes || dist - sons[i]->getRadius() < secondDist){
secondRes = sons[i];
secondDist = dist - sons[i]->getRadius();
}
}
}
return res?res:secondRes;
}
node_t* getSon(const int i){
return sons[i];
}
/*
~store~
Adds a new subtree to this node.
*/
void store(node_t* node, DistComp& di){
//cout << "store called" << endl;
//cout << "Routing Object is ";
//di.print(MTreeNode<T,DistComp>::routingObject,cout) << endl;
//cout << "radius is " << MTreeNode<T,DistComp>::radius << endl;
//cout << "noderoutingobject is ";
// di.print(*node->getRoutingObject(),cout) << endl;
//cout << "node radius is " << node->getRadius() << endl;
// compute new radius from this and the new node
double dist = di(node_t::routingObject,*node->getRoutingObject());
//cout << " dist = " << dist << endl;
double rad = std::max(this->getRadius() , dist + node->getRadius());
//cout << "new radius is " << rad << endl;
node_t::radius = rad;
sons[node_t::count] = node;
node_t::count++;
node->setParent(this, di);
}
/*
~search~
Searches a son by scanning all entries.
*/
int search(const node_t* son) const{
for(int i=0;i<node_t::count;i++){
if(sons[i]==son){
return i;
}
}
return -1;
}
/*
~replace~
Replaces the entry at position ~index~ by ~replacement~.
*/
void replace(node_t* replacement, int index, DistComp& di){
sons[index] = replacement;
double dist = this->distance(replacement, di);
double rad = std::max(this->getRadius(), dist + replacement->getRadius());
node_t::radius = rad;
replacement->setParent(this, di);
}
/*
~print~
Writes a textual representation of this node to ~out~.
*/
virtual std::ostream& print(std::ostream& out, DistComp& di) const {
return print(out,true, di);
}
virtual std::ostream& print(std::ostream& out,
const bool printSubtrees,
DistComp& di ) const {
out << "( \"o = " ;
di.print( node_t::routingObject,out) << ", rad = "
<< node_t::radius << "\"";
if(printSubtrees){
out << " (";
for(int i=0;i<node_t::count;i++){
sons[i]->print(out,di);
}
out << " )";
}
out << ")";
return out;
}
/*
~getNoLeafs~
Returns the number of leafs for this subtree.
*/
virtual int getNoLeafs() const{
int sum = 0;
for(int i=0; i<node_t::count;i++){
sum += sons[i]->getNoLeafs();
}
return sum;
}
/*
~getNoEntries~
Returns the number of entries in this subtree.
*/
virtual int getNoEntries() const{
int sum = 0;
for(int i=0; i<node_t::count;i++){
sum += sons[i]->getNoEntries();
}
return sum;
}
/*
~getNoNodes~
Returns the number of nodes of this subtree.
*/
virtual int getNoNodes() const{
int sum = 0;
for(int i=0; i< node_t::count;i++){
sum += sons[i]->getNoNodes();
}
return sum + 1;
}
size_t memSize() const{
size_t res = sizeof(*this) +
sizeof(void*) * node_t::maxEntries+1;
for(int i=0;i<node_t::count;i++){
res += sons[i]->memSize();
}
return res;
}
innernode_t* clone(){
innernode_t* res;
res = new innernode_t(node_t::minEntries,
node_t::maxEntries,
node_t::routingObject);
res->radius = node_t::radius;
res->distanceToParent = node_t::distanceToParent;
res->count = node_t::count;
for(int i=0;i<node_t::count;i++){
res->sons[i] = sons[i]->clone();
res->sons[i]->setParent(res);
}
return res;
}
private:
/*
2.4 Member variables
*/
node_t** sons;
};
/*
3 Class MTreeLeafNode
This class represents a leaf node of an m-tree.
*/
template<class T, class DistComp>
class MTreeLeafNode: public MTreeNode<T,DistComp>{
public:
typedef MTreeLeafNode<T,DistComp> leafnode_t;
typedef MTreeNode<T,DistComp> node_t;
/*
3.1 Constructor
*/
MTreeLeafNode(const int _minEntries, const int _maxEntries, const T& Or):
node_t(Or,0,0,_minEntries,_maxEntries){
Objects = new T*[node_t::maxEntries+1];
for(int i=0;i<node_t::maxEntries+1;i++){
Objects[i] = 0;
}
}
/*
3.2 Destructor
*/
virtual ~MTreeLeafNode(){
for(int i=0;i<node_t::maxEntries+1;i++){
if(Objects[i]){
delete Objects[i];
}
}
delete[] Objects;
}
/*
3.3 Methods
~isLeaf~
Of course, this function returns true.
*/
virtual bool isLeaf() const { return true; }
/*
~getNoLeafs~
Returns 1.
*/
virtual int getNoLeafs() const{
return 1;
}
/*
~getNoEntries~
Returns the number of entries stored within this leaf.
*/
virtual int getNoEntries() const{
return node_t::count;
}
/*
~getNoNodes~
Returns 1.
*/
virtual int getNoNodes() const {
return 1;
}
/*
~store~
Adds an entry to this leaf.
*/
void store(const T& o, DistComp& di){
Objects[node_t::count] = new T(o);
double dist = di(node_t::routingObject,o);
if(node_t::radius<dist){
node_t::radius=dist;
}
node_t::count++;
}
/*
~getObject~
Returns the object stored at index ~i~.
*/
T* getObject(const int i){
return Objects[i];
}
/*
~clear~
Removes all entries of this node. If ~deleteContent~ is true,
all contained objects are destroyed.
*/
virtual void clear(const bool deleteContent){
for(int i=0;i<node_t::count;i++){
if(deleteContent){
delete Objects[i];
}
Objects[i] = 0;
}
node_t::count = 0;
}
/*
~print~
write a textual representation fo this leaf to ~out~.
*/
std::ostream& print(std::ostream& out, DistComp& di) const{
out << "[ o = ";
di.print(node_t::routingObject,out) << ", rad = "
<< node_t::radius << " , content = \"";
for(int i=0;i<node_t::count;i++){
if(i>0) out << ", ";
di.print(*Objects[i],out) ;
}
out << "\"]";
return out;
}
std::ostream& print(std::ostream& out,
const bool printSubtrees,
DistComp &di) const{
return print(out, di);
}
size_t memSize() const{
size_t res = sizeof(*this) +
node_t::maxEntries * sizeof(void*);
for(int i=0;i<node_t::count;i++){
res += sizeof(* Objects[i]);
}
return res;
}
leafnode_t* clone(){
leafnode_t* res;
res = new leafnode_t(node_t::minEntries,
node_t::maxEntries,
node_t::routingObject);
res->radius = node_t::radius;
res->distanceToParent = node_t::distanceToParent;
res->count = node_t::count;
for(int i=0;i<node_t::count;i++){
res->Objects[i] = new T(*Objects[i]);
}
return res;
}
private:
/*
3.4 Member variables.
*/
T** Objects;
};
template <class T, class DistComp>
class RangeIterator{
public:
typedef RangeIterator<T,DistComp> rangeiterator_t;
typedef MTreeNode<T,DistComp> node_t;
typedef MTreeLeafNode<T,DistComp> leafnode_t;
typedef MTreeInnerNode<T,DistComp> innernode_t;
RangeIterator(const node_t* root, const T& _q,
const double _range, const DistComp& _di):
s(),q(_q), range(_range), di(_di) {
if(!root){
return;
}
di.reset();
if((root->centerDist(q, di) - range <= root->getRadius() )){
s.push(std::pair<const node_t*,int>(root,-1));
findNext();
}
}
bool hasNext(){
return !s.empty();
}
const T* next(){
if(s.empty()){
return 0;
}
std::pair<const node_t*,int> top = s.top();
findNext();
return ((leafnode_t*)top.first)->getObject(top.second);
}
size_t noComparisons() const{
return di.getCount();
}
int getNoDistFunCalls() const {
return di.getNoDistFunCalls();
}
private:
std::stack<std::pair<const node_t*, int> > s;
T q;
double range;
DistComp di;
void findNext(){
while(!s.empty()){
std::pair<const node_t*, int> top = s.top();
s.pop();
top.second++; // ignore current result
if(top.second < top.first->getCount() ){
if(top.first->isLeaf()){
leafnode_t* leaf =
(leafnode_t*) top.first;
while(top.second < leaf->getCount()){
double dist = di(*(leaf->getObject(top.second)),q);
if(dist<=range){
s.push(top);
return;
} else {
top.second++;
}
}
} else { // an inner node
innernode_t* inner = (innernode_t*) top.first;
s.push(top);
std::pair<node_t*, int>
cand(inner->getSon(top.second),-1);
if(cand.first->minDist(q,di) <= range){
s.push(cand);
}
}
}
}
}
};
/*
4 Class NNIterator
This iterator returns the content of an m-tree with increasing distance.
4.1 Auxiliary Class
The class NNContent encapsulates the entries of a priority queue.
*/
template<class T,class DistComp>
class NNContent{
public:
typedef MTreeNode<T,DistComp> node_t;
NNContent(const double _dist, node_t* _node):
dist(_dist), node(_node), obj(0){ }
NNContent(const double _dist, T* _obj):
dist(_dist), node(0), obj(_obj) {}
T* getObject() {
return obj;
}
node_t* getNode() {
return node;
}
bool operator<(const NNContent& b) const{
if(dist != b.dist){
return dist < b.dist;
}
if(node!=b.node) {
return node < b.node;
}
return obj < b.obj;
}
bool operator>(const NNContent& b) const{
if(dist != b.dist){
return dist > b.dist;
}
if(node!=b.node) {
return node > b.node;
}
return obj > b.obj;
}
private:
double dist;
node_t* node;
T* obj;
};
/*
4.2 NNContentComparator
This auxiliary class implements the less operator for two
NNContent objects.
*/
template<class T, class DistComp >
class NNContentComparator{
public:
bool operator()(const NNContent<T,DistComp>& a,
const NNContent<T,DistComp>& b){
return a < b;
}
};
template<class T, class DistComp>
class NNIterator{
public:
typedef MTreeNode<T,DistComp> node_t;
typedef MTreeLeafNode<T,DistComp> leafnode_t;
typedef MTreeInnerNode<T,DistComp> innernode_t;
typedef NNContent<T,DistComp> nncontent_t;
/*
4.1 Constructor
*/
NNIterator(node_t* root, T& _ref, DistComp _di ):
ref(_ref), q(), di(_di) {
if(root!=0){
double dist = root->minDist(ref, di);
q.push(nncontent_t(dist,root));
}
}
bool hasNext() const{
return !q.empty();
}
T* next(){
if(q.empty()){
return 0;
}
nncontent_t top = q.top();
q.pop();
// for nodes, push the sons/objects to q
while(top.getObject()==0){
node_t* node = top.getNode();
if(node->isLeaf()){
leafnode_t* leaf = (leafnode_t*) node;
for(int i=0;i<leaf->getCount();i++){
T* o = leaf->getObject(i);
double dist = di( *o,ref);
q.push(nncontent_t(dist,o));
}
} else {
innernode_t* inner = (innernode_t*) node;
for(int i=0;i<inner->getCount(); i++){
node_t* son = inner->getSon(i);
double dist = son->minDist(ref, di);
q.push(nncontent_t(dist, son));
}
}
top = q.top();
q.pop();
}
return top.getObject();
}
int getNoDistFunCalls() const {
return di.getNoDistFunCalls();
}
size_t distStorageSize() const {
return di.distStorageSize();
}
private:
T ref;
std::priority_queue<nncontent_t,
std::vector<nncontent_t >,
std::greater<nncontent_t > > q;
DistComp di;
};
/*
4 Class MMTree
This is the main class of this file. It implements a main memory based m-tree.
*/
template<class T, class DistComp>
class MMMTree{
public:
typedef MTreeLeafNode<T,DistComp> leafnode_t;
typedef RangeIterator<T,DistComp> rangeiterator_t;
typedef NNIterator<T,DistComp> nniterator_t;
typedef MTreeNode<T, DistComp> node_t;
typedef MMMTree<T,DistComp> mmmtree_t;
typedef MTreeInnerNode<T,DistComp> innernode_t;
/*
4.1 Constructor
Creates an empty tree.
*/
MMMTree(int _minEntries, int _maxEntries, DistComp& _di):
minEntries(_minEntries), maxEntries(_maxEntries), root(0), di(_di){}
/*
4.2 Destructor
Destroyes this tree.
*/
~MMMTree(){
if(root){
delete root;
}
}
/*
4.3 Methods
~getNoLeafs~
Returns the number of leafs of this tree.
*/
int getNoLeafs() const{
if(!root){
return 0;
} else {
return root->getNoLeafs();
}
}
/*
~getNoEntries~
Returns the number of stored objects.
*/
int getNoEntries() const{
if(!root){
return 0;
} else {
return root->getNoEntries();
}
}
/*
~getNoNodes~
Returns the number of nodes of this tree.
*/
int getNoNodes() const{
if(!root){
return 0;
} else {
return root->getNoNodes();
}
}
size_t noComparisons() const{
return di.getCount();
}
size_t memSize() const {
size_t res = sizeof(*this);
if(root){
res += root->memSize();
}
return res;
}
/*
~insert~
Adds ~o~ to this tree.
*/
void insert(T & o){
if(!root){
root=new leafnode_t(minEntries,maxEntries,o);
}
root = insert(root,o,di);
}
/*
~print~
Writes a textual representation of this tree to ~out~.
*/
std::ostream& print(std::ostream& out){
if(root==0){
out << "empty";
} else {
root->print(out,di);
}
return out;
}
/*
~rangeSearch~
Returns a range iterator iterating over all Elements with distance
to q smaller or equals to range.
*/
rangeiterator_t* rangeSearch(const T& q, double range) const {
return new rangeiterator_t(root,q,range, di);
}
/*
~nnSearch~
Returns an iterator returning the elements of this tree in
increasing order to the reference object.
*/
nniterator_t* nnSearch(T& ref){
return new nniterator_t(root,ref,di);
}
const DistComp& getDistComp(){
return di;
}
node_t* getRoot() {
return root;
}
mmmtree_t* clone(){
mmmtree_t* res = new mmmtree_t(minEntries, maxEntries, di);
if(root){
res->root = root->clone();
}
return res;
}
private:
int minEntries;
int maxEntries;
node_t* root;
DistComp di;
/*
~insert~
Inserts a new entry to the tree rooted by root, returns the root of the
tree that contains all old entries and o (may be the same root as the
parameter.
*/
static node_t* insert(node_t* root, const T& o, DistComp& di){
node_t* son = root;
while(!son->isLeaf()){
son->increaseRadius(o,di);
son = ((innernode_t*)son)->getBestSon(o, di);
}
((leafnode_t*)son)->store(o,di);
return split(root,son, di);
}
/*
~selectSeeds~
selects two nodes from the given node ahich are the seeds for
splitting.
*/
static std::pair<int,int> selectSeeds(node_t* node,
DistComp& dc){
//variants
// 1: use two random numbers
// 2: use one random number and the entry with maximum distance to it
// 3: build a sample from this node, take the two nodes form the sample
// with minium overlapping area
// temporarly use the first variant
//int seed1 = std::rand()%node->getCount();
//int seed2 = std::rand()%(node->getCount()-1);
//if(seed2>=seed1){
// seed2++;
//}
//return std::pair<int,int>(seed1,seed2);
// second variant
int seed1 = std::rand()%node->getCount();
int seed2 = seed1;
double dist = 0;
if(node->isLeaf()){
leafnode_t* node1 = (leafnode_t*) node;
const T* ro = node1->getObject(seed1);
for(int i=0;i<node1->getCount();i++){
if(i!=seed1){
const T* ro2 = node1->getObject(i);
double d2 = dc(*ro,*ro2);
if((seed1==seed2) || d2>dist){
dist = d2;
seed2 = i;
}
}
}
} else {
innernode_t* node1 = (innernode_t*) node;
const T* ro = node1->getSon(seed1)->getRoutingObject();
for(int i=0;i<node1->getCount();i++){
if(i!=seed1){
const T* ro2 = node1->getSon(i)->getRoutingObject();
double d2 = dc(*ro,*ro2);
if((seed1==seed2) || d2>dist){
dist = d2;
seed2 = i;
}
}
}
}
std::pair<int,int> res(seed1,seed2);
return res;
}
/*
~Create partition~
Distributes the content of a node two two new nodes using ~firstSeed~ and
~secondSeed~ for the seeds.
*/
static std::pair<node_t*,node_t*>
createPartition(
const node_t* node,
const int firstSeed,
const int secondSeed,
DistComp& di) {
if(node->isLeaf()){
leafnode_t* nodeL = (leafnode_t*) node;
T* obj1 = nodeL->getObject(firstSeed);
T* obj2 = nodeL->getObject(secondSeed);
leafnode_t* first =
new leafnode_t(node->getMinEntries(),
node->getMaxEntries(),
*obj1);
leafnode_t* second =
new leafnode_t(node->getMinEntries(),
node->getMaxEntries(),
*obj2);
leafnode_t* in;
for(int i=0;i<node->getCount();i++){
T* obj = nodeL->getObject(i);
double dist1 = first->centerDist(*obj,di);
double dist2 = second->centerDist(*obj,di);
if(dist1==dist2){
in = first->getCount()<second->getCount()?first:second;
} else {
in = dist1<dist2?first:second;
}
in->store(*obj,di);
}
return std::pair<node_t*,node_t*>
(first,second);
} else { // process inner node
innernode_t* nodeI= (innernode_t*) node;
const T* obj1 = nodeI->getSon(firstSeed)->getRoutingObject();
const T* obj2 = nodeI->getSon(secondSeed)->getRoutingObject();
innernode_t* first =
new innernode_t(node->getMinEntries(),
node->getMaxEntries(),
*obj1);
innernode_t* second =
new innernode_t(node->getMinEntries(),
node->getMaxEntries(),
*obj2);
innernode_t* in;
for(int i=0;i<node->getCount();i++){
node_t* son = nodeI->getSon(i);
double dist1 = first->distance(son,di);
double dist2 = second->distance(son,di);
if(dist1==dist2){
in = first->getCount()<second->getCount()?first:second;
} else {
in = dist1<dist2?first:second;
}
in->store(son,di);
}
return std::pair<node_t*,node_t*>(first,second);
}
}
/*
~split~
Performs a split up to the root of this tree.
*/
static node_t* split(node_t* root,
node_t* currentNode,
DistComp& di){
while((currentNode!=0) && currentNode->isOverflow()){
std::pair<int,int> seeds = selectSeeds(currentNode,di);
std::pair<node_t*,node_t*> part =
createPartition(currentNode,seeds.first,
seeds.second, di);
if(currentNode->getParent()==0){ // splitted root
const T* ro = rand()%1>0?part.first->getRoutingObject()
:part.second->getRoutingObject();
innernode_t* root2 =
new innernode_t(
currentNode->getMinEntries(),
currentNode->getMaxEntries(),
*ro);
currentNode->clear(currentNode->isLeaf());
delete currentNode;
currentNode = 0;
root2->store(part.first,di);
root2->store(part.second, di);
root = root2;
} else {
innernode_t* parent = (innernode_t*) currentNode->getParent();
int index = parent->search(currentNode);
assert(index >=0);
parent->replace(part.first,index,di);
parent->store(part.second,di);
currentNode->clear(currentNode->isLeaf());
delete currentNode;
currentNode = parent;
}
}
return root;
}
};
#endif