在C中删除节点形成二叉搜索树

时间:2014-11-21 16:50:35

标签: c recursion data-structures binary-tree binary-search-tree

我正在尝试编写一个从二叉搜索树中删除节点(任何节点)的函数。由于某种原因,删除功能删除多个节点。这是一个递归函数,当涉及到resursion时我有点困惑。下面是我的代码,有人可以帮我弄清楚出了什么问题。 提前致谢

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


typedef struct node *nodeP;
typedef struct StudentRoster *StudentRosterP;

struct node
{
    nodeP left;
    char name[30];
    int ID;
    nodeP right;            
};

struct StudentRoster
{
    nodeP root;
    int size;
};

//create a new student roster
StudentRosterP newStudentRoster()
{
    StudentRosterP new;
    new = NULL;
    new = malloc(sizeof(struct StudentRoster));
    if (new == NULL)
        {
            fprintf(stderr, "Error: Memory allocation for Student Roster failed\n");
            return NULL;
        }
    else
        {
            new->root = NULL;
            new->size = 0;
            return new;
        }   
}

//creates a new node to store student information
nodeP newNode(char *name, int ID)
{
    nodeP new;
    new = NULL;
    new = malloc(sizeof(struct node));
    if(new == NULL)
    {
        fprintf(stderr, "Memory allocation for the node failed.\n");
        return NULL;
    }
    else
    {
        new->left = NULL;
        new->right = NULL;
        new->ID = ID;
        strcpy(new->name, name);
        return new;
    }
}
//function to insert student. this is a helper function, recursive call

void insert(nodeP root, int ID, char * name)
{

     if (ID == root->ID)
     {
         printf("Duplicate IDs not allowed\n");
         return;
     }
     else {
           if(ID < root->ID)
            {
               if(root->left == NULL)
               {
                   root->left = newNode(name, ID);
               }
               else
               {
                root = root->left;
                insert(root, ID, name); 
               }
            }
            else 
            {
               if(root->right == NULL)
               {
                   root->right = newNode(name, ID);
               }
               else
               {
                    root = root->right;
                    insert(root, ID, name);
               }
            }
     }
}

//to insert new student
void insertStudentRoster(StudentRosterP roster, char * name, int ID)
{

     nodeP root = roster->root;     
        if(roster->root == NULL)     // its empty 
        {
             roster->root = newNode(name, ID);         
        }

        else {                
            if (ID == roster->root->ID)
            {
                printf("Duplicate IDs not allowed\n");
                return;
            }
            else
            {
                insert(roster->root, ID, name);
            }            
        }     
}

/*
 * Helper function for removeStudentRoster
 * finds a node to be deleted and returns its pointer
 */
nodeP findMin(nodeP node)
{
    while(node->left != NULL)
    {
        node = node->left;
    }
    return node;         
}

//removes the node to be deleted
//returns null pointer to the parent function
//This is where I am having problem

nodeP delete(nodeP root, int ID)
{
    if(root == NULL)
    {
        return root;
    }

    else if(ID < root->ID)
    {
        root->left = delete(root->left, ID);
    }
    else if(ID > root->ID)
    {
        root->right = delete(root->right, ID);
    }
    else
    {
        if (root->left == NULL && root->right == NULL)
        {

           free(root);
           root = NULL;
        }

        else if(root->left == NULL)
        {
            nodeP temp = root;
            root = root->right;
            free(temp);
        }
        else if(root->right == NULL)
        {
            nodeP temp = root;
            root = root->left;
            free(temp);
        }
        else
        {
            nodeP temp = findMin(root->right);
            root->ID = temp->ID;
            strcpy(root->name, temp->name);
            root->right = delete(root->right, temp->ID);

        }
        return root;
    }
}

/*
 * Removes the node containing the matching names
 * Parameters: StudentRoster, id
 */
void removeStudentRoster(StudentRosterP roster, int ID)
{
    if(roster == NULL)
    {
        printf("The Student roster does not exist\n");
        return;
    }
    else if(roster->root == NULL)
    {
        printf("The Student roster is empty\n");
        return;
    }
    else{
         //find the node to be deleted
        roster->root = delete(roster->root, ID);        
    }    
}

//for printing in ordered

void inOrder(nodeP node)
{
    if (node == NULL)
        return;
    inOrder(node->left);
    printf("ID #: %i, Name: %s \n", node->ID, node->name);
    inOrder(node->right);

}
/*
 * Displays all the entries in the Phone book in order
 * Display one person per line, ID followed by first name
 */

void displayStudentRoster(StudentRosterP roster)
{
   if (roster->root == NULL)    {
        printf("The Roster is empty");
        return;
    }
   else
    {
        inOrder(roster->root);
        return;        
    }    
}

int main()
{

    StudentRosterP newRoster;
    newRoster = newStudentRoster();
    insertStudentRoster(newRoster, "Alice", 10);
    insertStudentRoster(newRoster, "Jake", 8);

    insertStudentRoster(newRoster, "josh", 12);
    insertStudentRoster(newRoster, "Alen", 9);
    insertStudentRoster(newRoster, "Joe", 11);    


    removeStudentRoster(newRoster, 11);      //it removes the whole roster when removing a node  that has no childrens
//when removing the root, it also removes the right child

    displayStudentRoster(newRoster);



    return (EXIT_SUCCESS);
}

1 个答案:

答案 0 :(得分:1)

在您的删除功能中,您的return放错地方(仅在IDroot->ID匹配时才会到达)。你需要将它移过下一个右括号,将它放在else之后:

        }
        /* "return root;" was here... */
    }
    return root; /* ..but should be here. */
}

此外,当ID匹配时(在最后else中)删除节点时,逻辑似乎是错误的。您需要做的是将右分支移动到左分支中最右边的节点,或者将左分支移动到右分支的最左边节点...然后返回该分支。因此,使用您的findMin()找到右侧分支的最左侧部分,我们可以这样做:

        else
        {
            nodeP temp = findMin(root->right);
            temp->left = root->left;
            temp = root;
            root = root->right;
            free(temp);
        }