簡體   English   中英

二進制搜索樹中拒絕刪除的節點

[英]Node Refusing to Delete in Binary Search Tree

我目前正在編寫一個程序,該程序將從二叉搜索樹中刪除一個節點(除其他事項外,但刪除是我的問題),並且刪除的最后一步(尤其是刪除a的最后一步)存在問題有2個孩子的節點。

我要刪除的方式就是這里描述的方式。 我選擇最左邊的子節點(如果在根的右側)或最右邊的子節點(如果在左側),並用該值替換要刪除的節點的值,然后刪除我剛從中復制的節點。

我已完成所有步驟,除了刪除從中復制的節點; 由於某種原因,我的代碼未正確刪除它,並為我剛嘗試刪除的節點創建了一個隨機數值和一個隨機父值。 我相信這是由於樹中某個地方的未修復鏈接引起的,但是作為一個沒有經驗的程序員,我找不到它。 希望有更精通BST的人可以對我有所幫助。

這是我的代碼(我僅包含影響刪除功能的代碼,我認為沒有必要包含諸如destroy函數之類的后續代碼):

#include <iostream>

using namespace std;

struct node
{
    int data; //Stores data within the trees pointers
    node * parent; //Used to move up in the tree
    node * left; //Used to move left in the tree
    node * right; //Used to move right in the tree
};

node * create (int data, node **tree); //Function to insert elements into the tree

void printTree (node * tree); //Function to print the tree

node *search(int key, node *tree); //Function to find data in the tree

node * delNode (node * tree, node * root); //Function to delete data from the tree

node * findSmallestRight (node * tree, node **smallest);

node * findLargestLeft (node * tree, node **smallest);

int main()
{
    node * root = NULL; //Root will be the first element in the tree
    node * current = NULL; //Return value for insert function to keep changes
    int value; //Value entered by user

    while (true) //Loop to fill tree with data
    {
        cout << "Enter an integer, 0 to quit" << endl;
        cin >> value;
        if (value == 0) //Quit when 0 is entered, BEFORE entering it into the tree
            break;
        current = create(value, &root); //Insert value into the tree
        cout << "After inserting " << value << " tree is:" << endl;
        printTree(root); //Print the tree
    }
    while (true) //Loop to delete data from tree
    {
        cout << "Search for a value to delete from the tree, 0 to quit" << endl;
        cin >> value;
        if (value == 0)
            break;
        current = search(value, root); //Find the value in the tree
        if (current == NULL)
            cout << value << " is not in tree. Could not delete." << endl;
        else
        {
            root = delNode(current, root); //Delete the data
            cout << value << " has been deleted. The tree is now:" << endl;
            printTree(root); //print the tree
        }
    }
    destroy(root); //Destroy the tree
    return 0;
}

void printNode (node * Node) //Function to print a node in the tree
{
    cout << "addr= " << Node << " parent= " << Node->parent << " left= " << Node->left << " right= " << Node->right << " data= " << Node->data << endl;
}

node * createNode (int data) //Function to create a new node in the tree
{
    node * newNode = NULL; //Create a new pointer
    newNode = new node; //Make that pointer a node
    newNode->data = data; //Fill it with data
    newNode->left = NULL; //Make it point left to NULL
    newNode->right = NULL; //and right to NULL
    return newNode;
}

node * create (int data, node **tree) //Function to insert elements into the tree
{
    node * newNode = NULL; //Create a new pointer
    if ((*tree) == NULL) //Check if tree exists already
    {
        //If it doesn't, create a new node and make it the root
        newNode = createNode(data);
        *tree = newNode;
        (*tree)->parent = NULL; //Root has a parent of NULL
    }
    else if (data < (*tree)->data) //If the data is smaller than root, insert on the left
    {
        if ((*tree)->left == NULL)//If there is no node on the left, create a new one and point to it
        {
            newNode = createNode(data);
            (*tree)->left = newNode;
            newNode->parent = *tree;
        }
        else
        {
            newNode = create(data, &((*tree)->left));//If there is a node on the left, repeat function until there isn't
        }
    }
    else //If the data is greater than or equal to root, insert on the right
    {
        if ((*tree)->right == NULL)
        {
            newNode = createNode (data); //If there is no node on the right, create a new one and point to it
            (*tree)->right = newNode;
            newNode->parent = *tree;
        }
        else
        {
            newNode = create(data, &((*tree)->right)); //If there is a node on the right, repeat function until there isn't
        }
    }
    return newNode; //Return the new node to keep the changes to the value
}

void printTree (node * tree) //Function to print the tree
{
    if (tree != NULL) //Check if tree actually existsreturn root;
    {
        //Recursively print the left side, then the root, then the right side
        printTree(tree->left);
        printNode(tree);
        printTree(tree->right);
    }
}

node *search(int key, node *tree) //Function to find data in the tree
{
    if (tree == NULL || tree -> data == key)
    {
        return tree; //If the data either does not exist or has been found, return
    }
    if (key < tree->data)
    {
        return search(key, tree->left); //If the data is less than the current data, keep checking the left
    }
    else
    {
        return search(key, tree->right); //If the data is more than the current data, keep checking the right
    }
}

node * delNode (node * tree, node * root)
{
    node * parent; //Node for quick-reference and manipulation of tree's parent
    if (tree->parent != NULL) //If tree value is not root assign a parent (root has parent of NULL so assigning would crash)
    {
        parent = tree->parent;
    }
    node * curr = tree;
    //Removing node with 2 children on right
    //There would also be cases for no children, 1 child, and 2 children on left but I did not include them as the two former are done and the latter can be copied once this is solved :)
    else if (tree->left != NULL && tree->right != NULL && parent->right == tree && parent != NULL)
    {
        node * smallest; //Node to find smallest data value on left side
        //Initialise and make it point to nothing
        smallest = new node;
        smallest->left = NULL;
        smallest->right = NULL;
        smallest->parent = NULL;

        node * nReplace = NULL; //Node to replace data in tree
        //Initialise and make it point to nothing
        nReplace = new node;
        nReplace->left = NULL;
        nReplace->right = NULL;
        nReplace->parent = NULL;

        nReplace = findSmallestRight(tree, &smallest); //Function to find smallest data value on right side
        tree->data = nReplace->data; //Replace tree's data with the new data
        cout << nReplace << " " << nReplace->data << endl; //Debugging code
        delete nReplace; //Delete nReplace
        cout << nReplace << " " << nReplace->data << endl; //Debugging code
    }
    return root; //Return root to keep changes in tree
}

node * findSmallestRight (node * tree, node **smallest) //Function to find smallest data value on right side
{
    node * parent = tree->parent; //Node for easy manipulation of tree's parent
    //Check if current value is a potential candidate for smallest
    if (tree->left == NULL && tree->right == NULL && parent->left == tree)
    {
        *smallest = tree; //If it is, make smallest equal to it
    }
    if (tree->left == NULL && tree->right != NULL) //Check if the are only branches on the right
    {
        findSmallestRight (tree->right, smallest); //Recurse through the right
    }
    else if (tree->left != NULL && tree->right == NULL) //Check if there are only branches on the left
    {
        findSmallestRight (tree->left, smallest); //Recurse through the left
    }
    else if (tree->left == NULL && tree->right == NULL) //Check if there are no branches on both sides
    {
        return *smallest; //Return the smallest
    }
    else
    {
        //If there are branches on both sides recurse through both
        findSmallestRight (tree->left, smallest);
        findSmallestRight (tree->right, smallest);
    }
    return *smallest; //Return the smallest
}

我認為您的findSmallestRight()從遞歸到返回值都一團糟。

您只需要在Right子樹上找到SMALLEST元素即可,例如,對於右邊的孩子,要迭代它的Left孩子直到最后一個,這將是最小的。

代碼很簡單 :(首先查看圖片以了解名稱關聯)

if (current->left != NULL && current->right != NULL) //condition if you Current Node (to be deleted) has 2 Children
  {      if((current->right)->left!=NULL) //If Right Child has left child go till last leftmost child.
        {
            Node* leftCurrent;
            Node* leftCurrentPred;
            leftCurrentPred=current->right;
            leftCurrent=(current->right)->left;
            while(leftCurrent->left != NULL)
            {
                leftCurrentPred=leftCurrent;
                leftCurrent=leftCurrent->left;
            }
            current->data=leftCurrent->data;
            delNode(leftCurrent, root); //Delete leftCurrent node i.e node with no child
            leftCurrentPred->left=NULL;
            cout<<item<<" has been removed from the Tree."<<endl;
        }
        else
        {  //If Right Child of current doesn't has Left child it is itself smallest one.
            Node* temp=current->right;
            current->data=temp->data;
            current->right=temp->right;
            delNode(temp,root); //Delete temp node i.e node with no child
            cout<<item<<" has been removed from the Tree."<<endl;
        }
}

在此處輸入圖片說明

暫無
暫無

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

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