public void remove(String key) {
    // найти вершину с таким ключом
    Node node = getNode(key);
    if (node != null) {
      // если вершина не имеет сыновей
      if (hasNoChild(node)) {
        // просто удалить вершину
        removeNode(node);
      } else if (hasOneChild(node)) {
        // если вершина имеет одного сына
        // удалить вершину
        // заменить её сыном
        if (node.getLeftChild() != null) {
          replaceNode(node, node.getLeftChild());
        } else if (node.getRightChild() != null) {
          replaceNode(node, node.getRightChild());
        }
      } else if (hasTwoChild(node)) {
        // если вершина имеет 2 сыновей
        // найти правого сына вершины #2
        Node n1 = node.getRightChild();
        // найти левого сына вершины #2
        // продолжать выбирать левых сыновей, 
        // пока не будет найдена вершина, у которой нет левого сына
        Node lastLeft = findLastLeftChild(n1);
        Node parentLastLeft = lastLeft.getParent();
        Node rightChild = lastLeft.getRightChild();
        // заменить начальную вершину на найденную
        replaceForRemove(node, lastLeft);        
        // сделать правого сына найденной вершины левым сыном родителя найденной вершины
        if (parentLastLeft != node) {
          parentLastLeft.setLeftChild(rightChild);
        }
      }
    }



  }