簡體   English   中英

C++ 從二叉搜索樹中刪除節點

[英]C++ Delete node from binary search tree

我構建了一個二叉搜索樹,並插入了一些隨機值節點。 我正在嘗試實現一個刪除節點的功能,但由於某種原因它不起作用。 嘗試刪除給定節點時,被刪除節點的父節點和被刪除節點的子節點似乎不會“連接”。

誰能看到我做錯了什么? 我多次嘗試調試程序以查看我的錯誤在哪里,但我不明白如何將父級和子級連接在一起。

這是我的程序:

#include <iostream>
using namespace std;

struct Node
{
    int data;   
    Node* left; 
    Node* right;
};

Node* insertNode(Node* root, int n);
Node* newNode(int d);
Node* deleteNode(Node* root, int d);
Node* findMin(Node* root);

int main()
{
    int num;
    Node* rootPtr = NULL;
    Node* min;

    rootPtr = insertNode(rootPtr, 15);
    rootPtr = insertNode(rootPtr, 10);
    rootPtr = insertNode(rootPtr, 20);
    rootPtr = insertNode(rootPtr, 24);
    rootPtr = insertNode(rootPtr, 7);
    rootPtr = insertNode(rootPtr, 25);
    rootPtr = insertNode(rootPtr, 5);

    rootPtr = deleteNode(rootPtr, 7);

    cout << "\nEnter a number to search for: ";
    cin >> num;
    if(search(rootPtr, num))
        cout << "\nFound.";
    else
        cout << "\nNot found.";

    cout << endl;
    return 0;
}

Node* insertNode(Node* root, int n)
{
    if(root == NULL)                                
        root = newNode(n);                          
    else if(n <= root->data)                        
        root->left = insertNode(root->left, n);     
    else if(n > root->data)                         
        root->right = insertNode(root->right, n);
    return root;                                    
}

Node* newNode(int d)
{
    Node* newNode = new Node();             
    newNode->data = d;                      
    newNode->left = newNode->right = NULL;
    return newNode;                         
}

bool search(Node* root, int d)
{
    if(root == NULL)                    
        return false;
    else if(root->data == d)            
        return true;
    else if(d < root->data)             
        return search(root->left, d);   
    else if(d > root->data)             
        return search(root->right, d);  
}

Node* deleteNode(Node* root, int d)
{
    if(root == NULL)
        return root;
    else if(d < root->data)
        deleteNode(root->left, d);
    else if(d > root->data) 
        deleteNode(root->right, d);
    else
    {
        if(root->left == NULL && root->right == NULL)
        {
            delete root;
            root = NULL;
        }
        else if(root->left == NULL)     
        {
            Node* temp = root;      
            root = root->right;         
            delete temp;                
        }
        else if(root->right == NULL)    
        {
            Node* temp = root;          
            root = root->left;          
            delete temp;                
        }
        else
        {
            Node* temp = findMin(root->right);
            root->data = temp->data;            
            root->right = deleteNode(root->right, temp->data);
        }
    }
    return root;
}

Node* findMin(Node* root)
{
    if(root == NULL)
        cout << "\nThe tree is empty.";
    else
    {
        Node* temp = root;          
        while(temp->left != NULL)   
            temp = temp->left;      
        return temp;                
    }
}

deleteNode()函數中,節點未在遞歸的返回路徑中建立連接。 您可能需要像對insertNode()一樣使用函數的返回值。 例如,

else if(d < root->data)
    deleteNode(root->left, d);
else if(d > root->data) 
    deleteNode(root->right, d);

可能是(類似)

else if(d < root->data)
    root->left = deleteNode(root->left, d);
else if(d > root->data) 
    root->right = deleteNode(root->right, d);

另外, findMin()的調用者可能同時需要min節點及其父節點。 讓它同時返回。 deleteNode()您可能需要將父級的子級指針之一設置為NULL。

刪除節點時,還需要將存儲在父節點中的指針設置為NULL。

假設您有節點P和C,其中P.left = C,並且C是葉節點。 您的代碼將為C釋放內存,並將一個臨時變量(在程序中稱為root)設置為NULL。 (順便說一句,請使用nullptr而不是NULL。)但是,如果檢查P的內容,它仍然引用C的釋放地址。

#include <iostream>
using namespace std;

template<typename T>
class BinaryTree
{
private:
    struct Node
    {
        Node* parent = nullptr;
        Node* left = nullptr;
        Node* right = nullptr;
        T data{};
    };
    Node* root = nullptr;


public:
    Node* get_root() const { return root; }
    const Node* search(const T& _data);
    void insert(const T& _data);
    T find_max(Node* node);
    T find_min(Node* node);
    Node* delete_node(Node* node,T& data);
    void print(Node* node);

};


template <typename T>
const typename BinaryTree<T>::Node* BinaryTree<T>::search(const T& _data) 
{
    Node* current = root;

    while (current)
    {
        if (current->data == _data)
        {
            return current;
        }
        else if (current->data > _data)
        {
            current = current->left;
        }
        else if (current->data < _data)
        {
            current = current->right;
        }
    }
    return nullptr;
}

template <typename T>
void BinaryTree<T>::insert(const T& _data)
{
    Node* current = root;

    if (current == nullptr)
    {
        root = new Node;
        root->data = _data;
        return;
    }

    while (current)
    {
        if (current->data == _data)
        {
            return;
        }
        if (_data > current->data)
        {
            if (current->right == nullptr)
            {
                Node* newNode = new Node();
                newNode->data = _data;
                current->right = newNode;
                newNode->parent = current;
                return;
            }
            current = current->right;
        }
        else if (_data < current->data)
        {
            if (current->left == nullptr)
            {
                Node* newNode = new Node();
                newNode->data = _data;
                current->left = newNode;
                newNode->parent = current;
                return;
            }
            current = current->left;
        }
    }
}


template <typename T>
void BinaryTree<T>::print(Node* node)
{
    if (node != nullptr)
    {
        print(node->left);
        std::cout << node->data << std::endl;
        print(node->right);
    }
}

//not used 
template <typename T>
T BinaryTree<T>::find_max(Node* node)
{
    
    if (node->right != NULL)
    {
        find_max(node->right);
    }
    else {
        cout << node->data << std::endl;
    }
    return node->data;

}

template <typename T>
T BinaryTree<T>::find_min(Node* node)
{
    if (node->left != NULL)
    {
        find_max(node->left);
    }
    else {
        cout << node->data << std::endl;
    }
    return node->data;

}

template <typename T>

typename BinaryTree<T>::Node* BinaryTree<T>::delete_node(Node* node, T& _data)
{
    if (node == NULL) {
        return NULL;
    }
    else if (_data < node->data) {
        node->left = delete_node(node->left, _data);
    }
    else if (_data > node->data) {
        node->right = delete_node(node->right, _data);
    }
    else {
        if (node->left == NULL) {
            Node* temp = node->right;
            delete node;
            return temp;
        }
        else if (node->right == NULL) {
            Node* temp = node->left;
            delete node;
            return temp;
        }
        else {
            node->data = find_min(node->right);
            node->right = delete_node(node->right, node->data);
        }
    }
    return node;
}




int main()
{
    BinaryTree<int> tree;
    int numb{};

    tree.insert(15);
    tree.insert(11);
    tree.insert(100);
    tree.insert(16);
    tree.insert(13);
    tree.insert(18);
    tree.insert(16);
    tree.insert(10);

    tree.print(tree.get_root());
    cout << endl << endl;
    cout << "Max: ";
    tree.find_max(tree.get_root());
    cout << endl << endl;
    cout << "Min: ";
    tree.find_min(tree.get_root());
    tree.print(tree.get_root());
    
    while (tree.search(numb)==nullptr) {
        cout << "Choose Number To Delete: ";
        cin >> numb;
    }
    
    cout << endl << endl;
    tree.delete_node(tree.get_root(), numb);
    tree.print(tree.get_root());

    return 0;
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM