private Node merge(Node node, Node other) { if (node == null) { return copyRecursive(other); } else if (other == null) { return node; } else if (!inSameSubtree(node.bits, other.bits, Math.max(node.level, other.level))) { return makeSiblings(node, copyRecursive(other)); } else if (node.level > other.level) { long branch = other.bits & node.getBranchMask(); if (branch == 0) { node.left = merge(node.left, other); } else { node.right = merge(node.right, other); } return node; } else if (node.level < other.level) { Node result = createNode(other.bits, other.level, other.weightedCount); long branch = node.bits & other.getBranchMask(); if (branch == 0) { result.left = merge(node, other.left); result.right = copyRecursive(other.right); } else { result.left = copyRecursive(other.left); result.right = merge(node, other.right); } return result; } // else, they must be at the same level and on the same path, so just bump the counts double oldWeight = node.weightedCount; weightedCount += other.weightedCount; node.weightedCount = node.weightedCount + other.weightedCount; node.left = merge(node.left, other.left); node.right = merge(node.right, other.right); if (oldWeight < ZERO_WEIGHT_THRESHOLD && node.weightedCount >= ZERO_WEIGHT_THRESHOLD) { nonZeroNodeCount++; } return node; }
private void insert(long bits, double weight) { long lastBranch = 0; Node parent = null; Node current = root; while (true) { if (current == null) { setChild(parent, lastBranch, createLeaf(bits, weight)); return; } else if (!inSameSubtree(bits, current.bits, current.level)) { // if bits and node.bits are not in the same branch given node's level, // insert a parent above them at the point at which branches diverge setChild(parent, lastBranch, makeSiblings(current, createLeaf(bits, weight))); return; } else if (current.level == 0 && current.bits == bits) { // found the node double oldWeight = current.weightedCount; current.weightedCount += weight; if (current.weightedCount >= ZERO_WEIGHT_THRESHOLD && oldWeight < ZERO_WEIGHT_THRESHOLD) { ++nonZeroNodeCount; } weightedCount += weight; return; } // we're on the correct branch of the tree and we haven't reached a leaf, so keep going down long branch = bits & current.getBranchMask(); parent = current; lastBranch = branch; if (branch == 0) { current = current.left; } else { current = current.right; } } }
/** * Remove the node if possible or set its count to 0 if it has children and it needs to be kept * around */ private Node tryRemove(Node node) { if (node == null) { return null; } if (node.weightedCount >= ZERO_WEIGHT_THRESHOLD) { --nonZeroNodeCount; } weightedCount -= node.weightedCount; Node result = null; if (node.isLeaf()) { --totalNodeCount; } else if (node.hasSingleChild()) { result = node.getSingleChild(); --totalNodeCount; } else { node.weightedCount = 0; result = node; } return result; }