简体   繁体   中英

Stuck at deleting node from Binary Search Tree

I have been trying to follow the textbook "Introduction to Algorithms" but I'm stuck at the following step when deleting a node from a BST - when the node to be deleted has both children

My code is below:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "bst.h"


void error()
{
    fprintf(stderr, "%s\n", "Error assigning memory to node");
    exit(1);
}

void insert(node **root, int key)
{
    node *t1, *t2;

    if (*root == NULL) {
        printf("Root is null\n");
        *root = (node *)malloc(sizeof(node));
        if (*root==NULL) {
            fprintf(stderr, "%s\n", "Cannot allocate memory for node in Insert");
            exit(1);
        }
        (*root)->key = key;
        (*root)->left = (*root)->right = NULL;
    }
    else {
        printf("Root contains data. Inserting new node.\n");
        t1 = *root;

        while (t1 != NULL) {
            t2 = t1;

            if (key < t1->key)
                t1 = t1->left;
            else
                t1 = t1->right;
        }

        if(key < t2->key) {
            t2->left = (node *) malloc(sizeof(node));
            t2 = t2->left;
            if (t2==NULL)
                error();
            t2 -> key = key;
        }
        else {
            t2->right = (node *) malloc(sizeof(node));
            t2 = t2->right;
            if (t2==NULL)
                error();
            t2->key = key;
        }
    }

    
}

void inorder(node * root)
{
    if (root!=NULL) {
        inorder(root->left);
        printf("%d ->", root->key);
        inorder(root->right);
    }
}

node * search(node *root, int key)
{
    node * t = root;

    while (t!=NULL)
    {
        if (key == t->key)
            return t;
        else if (key < t->key)
            t = t->left;
        else
            t = t->right;
    }
    return NULL;
}

node * getparent(node * root, int key)
{
    node * t = root, *parent = NULL;

    while (t!=NULL)
    {   
        if (key == t->key)
            return parent;
        else if (key < t->key)
            t = t->left;
        else
            t = t->right;
        parent = t;
    }
    return NULL;
}

node * delete(node *root, int key)
{
    node * todelete = search(root,key), *parent = getparent(root, key), *y;
    if (todelete==NULL) {
        fprintf(stderr, "%s\n", "Key not found");
        exit(2);
    }

    if (todelete->left == NULL && todelete->right==NULL) { //Deleting node with no children
        if (todelete == parent->left)
            parent->left = NULL;
        else
            parent->right = NULL;
        free(todelete);
        return root;
    }
    else if (todelete->left && !todelete->right) {
        if (todelete == parent->left)
            parent->left = todelete->left;
        else
            parent->right = todelete->right;
        free(todelete);
        return root;
    }
    else if (todelete->right & !todelete->left) {
        if (todelete == parent->left)
            parent->left = todelete->left;
        else
            parent->right = todelete->right;
        free(todelete);
        return root;
    }
    else
    {
        node * yparent = NULL;
        y= todelete->right;
        while (y->left!=NULL)
        {
            y = y->left;
            yparent = y;
        }
        if(yparent != todelete) {
            //stuck here
        }
    }


}

bst.h:

struct treenode
{
    int key;
    struct treenode *left;
    struct treenode *right;
};

typedef struct treenode node;

node * getparent(node * root, int key);
void insert(node **root, int key);
node * search(node *root, int key);
node * delete(node *root, int key);
void inorder(node * root);

Any guidance would be much appreciated. I should be trying to set the y = y->right and then set todelete->right = y correct?

I'm stuck at the following step when deleting a node from a BST - when the node to be deleted has both children

It follows from the properties of a BST that if a node N has two children then every node in the subtree rooted at the left child is less than every node in the subtree rooted at the right child and vise versa . In particular, the largest node in the left subtree, L max , is less than all the nodes in the right subtree, and the least node in the right subtree, R min , is larger than all the nodes of the left subtree. These are the nodes immediately preceding and following N in an in-order traversal. Both of those descendants are easy to find, and neither has more than one child (else they could neither be max nor min in any subtree).

It follows, then, that if you want to delete node N then you may choose either L max or R min , delete it from the tree (which is easy because it has at most one child), and replace N with it. Alternatively, delete L max or R min , and replace the key of node N with the key of that deleted node.

Changed the code to the following and it works (for the delete functions):

static void transplant(node * root, node * u, node * v)
{
    node *uparent = getparent(root, u->key);
    node * vparent = getparent(root, v->key);

    if (uparent == NULL)
        root = v;
    else if (u == uparent->left)
        uparent->left = v;
    else uparent->right = v;

    if (v!=NULL)
        vparent = uparent;
}

node * delete(node *root, int key)
{
    node * todelete = search(root,key), *parent = getparent(root, key), *y;
    if (todelete==NULL) {
        fprintf(stderr, "%s\n", "Key not found");
        exit(2);
    }

    if (todelete->left == NULL && todelete->right==NULL) { //Deleting node with no children
        if (todelete == parent->left)
            parent->left = NULL;
        else
            parent->right = NULL;
        free(todelete);
        return root;
    }
    else if (todelete->left && !todelete->right) {
        if (todelete == parent->left)
            parent->left = todelete->left;
        else
            parent->right = todelete->left;
        free(todelete);
        return root;
    }
    else if (todelete->right && !todelete->left) {
        if (todelete == parent->left)
            parent->left = todelete->right;
        else
            parent->right = todelete->right;
        free(todelete);
        return root;
    }
    else {
        y = todelete->right;
        while(y->left!=NULL)
        {
            y = y->left;
        }

        node *yparent = getparent(root, y->key);
        if (yparent != todelete)
        {
            transplant(root, y, y->right);
            y->right = todelete->right;
            node * yrightparent = getparent(root, y->right->key);
            yrightparent = y;
        }
        transplant(root, todelete, y);
        y->left = todelete->left;
        node *yleftparent = getparent(root, y->left->key);
        yleftparent = y;
        free(todelete);
        return root;

    }

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM