docs: private void condenseTree(IndexTreePath<E> subtree, Stack<N> stack) {
      N node = getNode(subtree.getEntry());
      // node is not root
      if(!isRoot(node)) {
        N parent = getNode(subtree.getParentPath().getEntry());
        int index = subtree.getIndex();
        if(hasUnderflow(node)) {
          if(parent.deleteEntry(index)) {
            stack.push(node);
          }
          else {
            node.adjustEntry(parent.getEntry(index));
          }
        }
        else {
          node.adjustEntry(parent.getEntry(index));
        }
        writeNode(parent);
        // get subtree to parent
        condenseTree(subtree.getParentPath(), stack);
      }
  
      // node is root
      else {
        if(hasUnderflow(node) && node.getNumEntries() == 1 && !node.isLeaf()) {
          N child = getNode(node.getEntry(0));
          final N newRoot;
          if(child.isLeaf()) {
            newRoot = createNewLeafNode();
            newRoot.setPageID(getRootID());
            for(int i = 0; i < child.getNumEntries(); i++) {
              newRoot.addLeafEntry(child.getEntry(i));
            }
          }
          else {
            newRoot = createNewDirectoryNode();
            newRoot.setPageID(getRootID());
            for(int i = 0; i < child.getNumEntries(); i++) {
              newRoot.addDirectoryEntry(child.getEntry(i));
            }
          }
          writeNode(newRoot);
          height--;
        }
      }
    }