// split this M-tree into a list of trees having height level, which is used in the "splitting" phase of the BulkLoad algorithm // nCreated is the number of created subtrees, // level is the split level for the tree, // children is the list of the parents of each subtree, // name is the root for the subtrees names // the return value is the list of splitted subtrees's names GiSTlist<char *> * MT::SplitTree (int *nCreated, int level, GiSTlist<MTentry *> *parentEntries, const char *name) { GiSTlist<MTnode *> *oldList = new GiSTlist<MTnode *>; // upper level nodes MTnode *node = new MTnode; // this is because the first operation on node is a delete GiSTpath path; path.MakeRoot (); oldList->Append((MTnode *) ReadNode(path)); // insert the root do { // build the roots list GiSTlist<MTnode *> *newList = new GiSTlist<MTnode *>; // lower level nodes while (!oldList->IsEmpty()) { delete node; // delete the old node created by ReadNode node = oldList->RemoveFront(); // retrieve next node to be examined path = node->Path(); for (int i=0; i<node->NumEntries(); i++) { // append all its children to the new list path.MakeChild ((*node)[i].Ptr()->Ptr()); newList->Append((MTnode *)ReadNode(path)); path.MakeParent (); } } delete oldList; oldList = newList; } while (node->Level() > level); // stop if we're at the split level delete node; GiSTlist<char *> *newTreeNames = new GiSTlist<char *>; // this is the results list while (!oldList->IsEmpty()) { // now append each sub-tree to its root char newName[50]; sprintf (newName, "%s.%i", name, ++(*nCreated)); unlink (newName); // if this M-tree already exists, delete it MT *newTree = new MT; newTree->Create(newName); // create a new M-tree path.MakeRoot (); MTnode *rootNode = (MTnode *) newTree->ReadNode(path); // read the root of the new tree node = oldList->RemoveFront(); newTree->Append(rootNode, (MTnode *)node->Copy()); // append the current node to the root of new tree parentEntries->Append(node->ParentEntry()); // insert the original parent entry into the list newTreeNames->Append(strdup(newName)); // insert the new M-tree name into the list delete node; delete rootNode; delete newTree; } delete oldList; return newTreeNames; }
GiSTentry * MTnode::Union () const { Object *objTemp = NULL; if (!obj) { // retrieve the node's parent object MTentry *parentEntry = ParentEntry (); ((MTnode *)this)->obj = (objTemp = new Object(parentEntry->object())); delete parentEntry; } GiSTpath path = ((MTnode *)this)->Path(); MTentry *unionEntry = new MTentry; unionEntry->InitKey(); if (path.Level() > 1) { // len>=3 MTentry *parentEntry = ParentEntry (); if (parentEntry) { // copy the entry unionEntry->Key()->distance = parentEntry->Key()->distance; if (parentEntry->Key()->splitted) { unionEntry->Key()->splitted = TRUE; } delete parentEntry; } if (unionEntry->Key()->distance == -MaxDist()) { // compute the distance from the parent MTnode *parentNode = ((MT *)Tree())->ParentNode((MTnode *)this); MTentry *grandEntry = parentNode->ParentEntry(); unionEntry->Key()->distance = obj->distance(grandEntry->object()); unionEntry->Key()->splitted = TRUE; delete grandEntry; delete parentNode; } } unionEntry->SetObject(*obj); unionEntry->SetMaxRadius(0); unionEntry->SetMinRadius(MAXDOUBLE); mMRadius (unionEntry); // compute the radii if (objTemp) { delete objTemp; } ((MTnode *)this)->obj = NULL; return unionEntry; }