当前位置: 首页 > 知识库问答 >
问题:

用unique_ptr实现二叉搜索树中的迭代findMin()

章飞章
2023-03-14
class BinarySearchTree
{
public:
struct Node {
    Node(int k)
    {
        key = k;
        left = nullptr;
        right = nullptr;
    }
    int key;
    // This will auto-destroy all child nodes when this Node is destroyed
    std::unique_ptr<Node> left;
    std::unique_ptr<Node> right;
};

BinarySearchTree():
      m_root(nullptr)
    , m_depth(0)
{}

void deleteKey(int key)
{
    deleteKeyRec(key, m_root);
}

void deleteKeyRec(int key, std::unique_ptr<Node>& node)
{
    if (key == node->key) {
        // This node needs to be deleted and replaced with one of its children
        if (node->left == nullptr && node->right == nullptr) {
            // Node to be deleted has no children
            node = nullptr;
        }
        else if (node->left != nullptr && node->right == nullptr) {
            // Only left child present
            node = std::move(node->left);
        }
        else if (node->left == nullptr && node->right != nullptr) {
            // Only right child present
            node = std::move(node->right);
        }
        else {
            // Both children present, find minimum node in left subtree and replace
            auto minNode = findMin(node->left);
            node->key = minNode->key;
            deleteKeyRec(minNode->key, minNode);                
        }
    }
    else if (key < node->key) {
        deleteKeyRec(key, node->left);
    }
    else if (key > node->key) {
        deleteKeyRec(key, node->right);
    }
}

std::unique_ptr<Node> findMin(std::unique_ptr<Node> & node)
{
    Node *current = node.get();
    while (current->left) {
        current = current->left.get();
    }
    return std::make_unique<Node>(current);
}

private:
    std::unique_ptr<Node> m_root;   // Clean-up all children when this object is destroyed
    int m_depth;

};
void deleteKeyRec(int key, std::unique_ptr<Node>& node)
{
    if (key == node->key) {
        // This node needs to be deleted and replaced with one of its children
        if (node->left == nullptr && node->right == nullptr) {
            // Node to be deleted has no children
            node = nullptr;
        }
        else if (node->left != nullptr && node->right == nullptr) {
            // Only left child present
            node = std::move(node->left);
        }
        else if (node->left == nullptr && node->right != nullptr) {
            // Only right child present
            node = std::move(node->right);
        }
        else {
            // Both children present, find minimum node in right subtree and replace 'node'
            Node *owner = nullptr;         // stays one step behind current after first iteration
            Node *current = node->right.get();
            while (current->left.get()) {
                owner = current;
                current = current->left.get();
            }

            //auto minNode = findMin(node->left.get());
            node->key = current->key;      // transfer the key here, we do not free the memory of this node.
            if (owner == nullptr) {
                // The right node of 'node' is the correct replacement as it has no children
                node->right = nullptr;  // delete the node from which key was copied
            }
            else {
                // A left node was found when traversing the right subtree of 'node', so that node's owner now will have no left child!
                // This left child thats being deleted has already had its key copied to 'node' via 'current'
                owner->left = nullptr;   // delete the node from which key was copied
            }
        }
    }
    else if (key < node->key) {
        deleteKeyRec(key, node->left);
    }
    else if (key > node->key) {
        deleteKeyRec(key, node->right);
    }
}

共有1个答案

封飞
2023-03-14

find函数应该返回一个指向所找到元素的引用/指针/迭代器。它根本不应该返回所属指针。同样,它也不应该将所属指针作为参数。它应该使用指向节点的引用/指针/迭代器。

每个对象/节点必须完全由一个std::unique_ptr所有。因此,如果不打算从树中删除找到的节点,则不应将其作为std::unique_ptr返回。

例如:

Node& findMin(const Node& node)
{
    Node *current = node.get();
    while (current->left) {
        current = current->left.get();
    }
    return *current;
}
 类似资料:
  • 我正在学习C++语言,我正在尝试编写BST,但是出了问题。我尝试添加元素到空树,根是NULL,但添加元素后,根仍然是NULL,尽管添加成功了(我在调试模式下看到,节点设置为tmp)。我不知道为什么会这样。

  • 我现在正在看罗伯特·塞奇威克的算法书。在这本书中,我试图理解方法在二叉搜索树中的实现。作者用BST实现了一个符号表。作者描述方法如下: 假设我们寻找秩为k的密钥(该密钥使得BST中的其他密钥精确地k个更小)。如果左子树中的键数t大于k,则我们在左子树中(递归地)寻找秩为k的键;如果t等于k,我们返回根处的键;如果t小于k,我们在右子树中递归地寻找秩为k-t-1的键。像往常一样,这个de-scrip

  • 现在我们已经证明保持 AVL树的平衡将是一个很大的性能改进,让我们看看如何增加过程来插入一个新的键到树。由于所有新的键作为叶节点插入到树中,并且我们知道新叶的平衡因子为零,所以刚刚插入的节点没有新的要求。但一旦添加新叶,我们必须更新其父的平衡因子。这个新叶如何影响父的平衡因子取决于叶节点是左孩子还是右孩子。如果新节点是右子节点,则父节点的平衡因子将减少1。如果新节点是左子节点,则父节点的平衡因子将

  • 我很难按我教授想要的格式打印出一个二叉搜索树。 他的格式是这样的: 我的代码: