/* This appends `this` to the node `node` */ NodePtr insert(NodePtr thIs, NodePtr node) { int la = thIs->level; // node to be inserted int lb = node->level; // node where insertation assert(la < lb); // node to be inserted must have lower level then parent //if (thIs->parent) assert(find_in_tree1(thIs) == true); NodePtr q = NULL; NodePtr chd = NULL; node->move(thIs); if (la == lb - 1) { node->child.push_back(thIs); thIs->parent = node; if (node->child.size() > MAX_NODE_SZ && node->tree->canSplit() ) // with us as additional child `node` is now too large :( return (node->reinserted || node->parent == NULL) ? split(node) : reinsert(node); } else // la < lb - 1 { chd = thIs->closest(node->child); q = insert(thIs, chd); } if ((node->updateCount + 1) % UPDATE_EVERY == 0) node->update(); else { if (q) node->remove(q); node->inflate(chd); } return q; }
NodePtr split(NodePtr thIs) { thIs->tree->increaseLevelSize(thIs->level); NodePtr p = new Node; NodePtr q = new Node; p->level = q->level = thIs->level; p->reinserted = q->reinserted = false; p->parent = q->parent = thIs->parent; p->tree = q->tree = thIs->tree; p->child.resize(MAX_NODE_SZ/2); q->child.resize(MAX_NODE_SZ/2 + 1); assert(thIs->child.size() == MAX_NODE_SZ+1); thIs->tree->ref = thIs->closest(thIs->child, FARTHEST); // farthest from centre std::sort(thIs->child.begin(), thIs->child.end(), compareDist); for (int i = 0; i < MAX_NODE_SZ+1; i++) assert(thIs->child[i]->parent == thIs); for (int i = 0; i < MAX_NODE_SZ/2 + 1; i++) q->child[i] = thIs->child[i]; for (int i = MAX_NODE_SZ/2+1; i<MAX_NODE_SZ+1; i++) p->child[i-MAX_NODE_SZ/2-1] = thIs->child[i]; for (int i = 0; i < MAX_NODE_SZ/2 + 1; i++) q->child[i]->parent = q; for (int i = MAX_NODE_SZ/2+1; i < MAX_NODE_SZ+1; i++) p->child[i-MAX_NODE_SZ/2-1]->parent = p; p->update(); q->update(); if (squaredist(thIs->centre, q->centre) < squaredist(thIs->centre, p->centre)) swap(p, q); thIs->child = p->child; // now our children do not know we are their parents and believe p is their parent for (int i = 0; i < thIs->child.size(); i++) thIs->child[i]->parent = thIs; thIs->reinserted = p->reinserted; thIs->update(); delete p; if (thIs == thIs->tree->root) // root split { // since we currently are root, make new root and make us and q its children thIs->tree->newRoot(thIs->level + 1); thIs->tree->root->child.push_back(thIs); thIs->parent = thIs->tree->root; thIs->tree->root->child.push_back(q); q->parent = thIs->tree->root; thIs->tree->root->update(); } else { thIs->tree->push_front(q); } // push_front? return q; }
// Each sample node has a rank randomly assigned to it, assign `node` from full tree void Node::routeNode(NodePtr node, int level) { NodePtr closest; double distMin2 = 0; // squared distance closest = NULL; if (tree->root == this) findClosest(level, node, distMin2, closest); if (closest != NULL && tree->root == this) /* When is this point reached? if the preceeding findClosest was called and succesed to set closest findClosest sets closest if we are `level` or src is in our circle (=> belongs to child of ours) => reached if we are not `level` and node is not child of us */ node->route = closest->route; else /* find closest was not successfull or we were not root */ { if (this->level == level) node->route = this->route; else /* not yet right level => go down one more */ node->closest(this->child)->routeNode(node, level); } }