从BinaryTree中删除BinaryTreeNode

Deleting a BinaryTreeNode from a BinaryTree

本文关键字:BinaryTreeNode 删除 BinaryTree      更新时间:2023-10-16

我有一个BinarySearchTree,它由节点组成,这些节点都是数据类型为student的模板类,其中student是一个具有name和grade私有变量的类。

目前我可以打印树,在树中找到名字和/或成绩,但我在从树中删除节点时遇到麻烦。

我试图删除所有有一个等级的学生<50(如此失败)。

一旦一个节点被删除,需要发生以下情况之一:

  1. 左子节点为空:用其右子节点替换该节点。
  2. 左子节点不为空:用左边最高的元素替换该节点分支。

我的理解是,如果这是树:

      1
     /  
    2    3
   /    /
  4  5  6  7

如果2不及格,即有一个等级<50

你会得到

     1
    /  
  4     3
       / 
    5  6  7

4是左分支中最高的元素。

如果这是树:

     1
    /  
   2     3
        / 
    5  6   7

和2失败

你会得到

     1
    /  
  5      3
        /  
       6   7

如果这是树:

     1
    /  
  2     3
 /     / 
 4  5  6  7

和1失败

你会得到

     5
    /  
  2     3
 /      / 
4      6  7

我一直有很多麻烦试图创建函数来做到这一点,目前我有:

void checkBranch()  //called from main - used to pass the root node to checkBranch()
{
checkBranch(studentTree.getRoot());
}
bool checkBranch(BTNode<Student>* currentNode)
{
if (currentNode != NULL)
{
    if (checkBranch(currentNode -> getLeft()))
    {
        deleteNode(currentNode, true);
    }  
    if (checkBranch(currentNode -> getRight()))
    {
        deleteNode(currentNode, false);
    }
    return (currentNode -> getData().getGrade() < 50.0);
}
else
{
    return false;
}
}

现在我正试图添加deleteNode功能,我只是停留在做什么/处理需要发生的事情:

void deleteNode(BTNode<Student> *parentNode, bool left)
{
BTNode<Student>* nodeToDelete;
if (left)
{
    nodeToDelete = parentNode->getLeft();
}
}

我是这样做到的:

template <typename dataType>
void BTree<dataType>::deleteNode(BTNode<dataType> *parentNode, bool left)   
{
    BTNode<dataType> *nodeToDelete;
    BTNode<dataType> *currentNode;
if (left)
{
    nodeToDelete = parentNode->getLeft();
}
else
{
    nodeToDelete = parentNode->getRight();
}
if (nodeToDelete->getLeft() == NULL)
{
    currentNode = nodeToDelete;
    if (left)
    {
        parentNode->setLeft(nodeToDelete->getRight());
    }
    else
    {
        parentNode->setRight(nodeToDelete->getRight());
    }
    delete nodeToDelete;
}
else
{
    BTNode<dataType>* greatestNode = nodeToDelete->getLeft();
    if (greatestNode->getRight() == NULL)
    {
        nodeToDelete->getLeft()->setRight(nodeToDelete->getRight()); 
        if (left)
        {
            parentNode->setLeft(nodeToDelete->getLeft());
        }
        else
        {
            parentNode->setRight(nodeToDelete->getLeft());
        }
    }
    else
    {
        while (greatestNode->getRight()->getRight())
        {
            greatestNode = greatestNode->getRight();
        }
        nodeToDelete->setData(greatestNode->getRight()->getData());
        BTNode<dataType> *nodeToDelete2 = greatestNode->getRight();
        greatestNode->setRight(greatestNode->getRight()->getLeft());
        delete nodeToDelete2;
    }
}
}

首先,你的checkBranch是错误的。如果根节点无效会发生什么?不会被删除。在这里,我建议一种更优雅的方法,使用回调方法,可以像这样:

int deleteNodesOnCondition(BTNode<Student>* node, bool(* condition)(BTNode<Student>*))
{
   int deleteCount = -1;
   if(condition != NULL)
   {
      deleteCount = 0;
      if(node != NULL)
      {
         deleteCount += deleteNodesOnCondition(node->getLeft(), condition);
         deleteCount += deleteNodesOnCondition(node->getRight(), condition);
         bool satisfied = condition(node);
         if(satified)
         {
            deleteNode(node);
            deleteCount += 1;
         }
      }
   }
   return deleteCount;
}
bool checkValidGrade(BTNode<Student> *node)
{
   return node != NULL && node->getData().getGrade() >= 50.0;
}
void checkBranch()
{
   deleteNodesOnCondition(studentTree.getRoot(), checkValidGrade);
}

对于delete实现,在找到== true的地方检查。注意:此代码未经过测试