protected NODE delete(NODE node, K key) {
   if (node == null) {
     // We've reached a leaf. Nothing to delete.
     return null;
   }
   int cmp = key.compareTo(node.key);
   if (cmp < 0) {
     // Key is less than the node. Delete in the left subtree.
     node.left = delete(node.left, key);
     node.size = size(node.left) + size(node.right) + 1;
     return node;
   } else if (cmp > 0) {
     // Key is greater than the node. Delete in the right subtree.
     node.right = delete(node.right, key);
     node.size = size(node.left) + size(node.right) + 1;
     return node;
   } else {
     // Delete the node.
     if (node.left == null) {
       // Replace node with its right subtree.
       return node.right;
     } else if (node.right == null) {
       // Replace node with its left subtree.
       return node.left;
     } else if (node.right.left == null) {
       // Replace node with its right subtree.
       // Move the left subtree to the right node.
       node.right.left = node.left;
       node.right.size += size(node.left);
       return node.right;
     } else {
       // Replace node with its successor (Hibbard).
       NODE s = min(node.right);
       NODE x = delete(node, s.key);
       node.key = s.key;
       node.value = s.value;
       return x;
     }
   }
 }
 protected NODE put(NODE node, K key, V value) {
   if (node == null) {
     // We've reached a leaf. Create a new node to store the new value.
     return createNode(key, value);
   }
   int cmp = key.compareTo(node.key);
   if (cmp < 0) {
     // Key is less than the node. Update the left subtree.
     node.left = put(node.left, key, value);
     node.size = size(node.left) + size(node.right) + 1;
     return node;
   } else if (cmp > 0) {
     // Key is greater than the node. Update the right subtree.
     node.right = put(node.right, key, value);
     node.size = size(node.left) + size(node.right) + 1;
     return node;
   } else {
     // Update the value on the node.
     node.value = value;
     return node;
   }
 }