简体   繁体   English

C ++二进制搜索树删除问题

[英]C++ Binary search tree delete issue

I am new on C++. 我是C ++的新手。 My background is from PHP and C#. 我的背景来自PHP和C#。 I implement Binary search tree in VC++ in Visual Studio 2005 我在Visual Studio 2005中的VC ++中实现了二进制搜索树

All operations are fine, I am facing the problem with delete in one particular scenario, ie when I try to delete head twice or more times. 所有操作都很好,在一种特定的情况下,即当我尝试删除head两次或多次时,我面临着删除的问题。

Proposed strategy is 建议的策略是

  1. Find minimum in the right sub tree 在右边的子树中找到最小值
  2. Replace the node you want to delete with minimum 用最少的数量替换要删除的节点
  3. delete minimum 删除最小值

In my code 8 is on the top, when I delete top, first time, than 11 become top from right sub tree, If I delete any other node, code is working fine, but if I delete top again(after deletion of 8 now it is 11) I got following error 在我的代码8中位于顶部,当我第一次删除top时,从右侧子树中删除11成为top,如果我删除任何其他节点,代码工作正常,但是如果我再次删除top(现在删除8之后是11)我收到以下错误

Windows has triggered a breakpoint in BinarySearchTreeByList.exe. Windows已在BinarySearchTreeByList.exe中触发了一个断点。

This may be due to a corruption of the heap, and indicates a bug in >BinarySearchTreeByList.exe or any of the DLLs it has loaded. 这可能是由于堆损坏所致,并表明> BinarySearchTreeByList.exe或其已加载的任何DLL中存在错误。

The output window may have more diagnostic information 输出窗口可能包含更多诊断信息

Following is complete code 以下是完整的代码

#include "stdafx.h"
#include <stdio.h>
#include <tchar.h>
#include <list>
#include <iostream>

typedef struct node
{
    node* left;
    node* right;
    node* parent;
    int val;
};

using namespace std;

void insert_node(node** iterate, int newVal, node* newParent);
void traverse(node* iterate);
void del(node** iterate, int newVal, char direction);


void traverse(node* iterate)
{
    if(iterate != NULL)
    {
        traverse(iterate->left);
        printf("%d ",iterate->val);
        traverse(iterate->right);
    }
}


void del(node** iterate, int newVal, char direction)
{

    if((*iterate) == NULL)
        return;

    if((*iterate)->val == newVal)
    {
        if((*iterate)->left == NULL && (*iterate)->right == NULL)
        {
            if(direction == 't')
            {
                node* deleted = *iterate;
                *iterate = NULL;
                free(deleted);
            }

            if(direction == 'l')
            {
                node* deleted = (*iterate)->parent->left;
                (*iterate)->parent->left = NULL;
                free(deleted);
            }

            if(direction == 'r')
            {
                node* deleted = (*iterate)->parent->right;
                (*iterate)->parent->right = NULL;
                free(deleted);
            }

            return;
        }

        if((*iterate)->left == NULL)
        {
            if(direction == 't')
            {
                node* deleted = *iterate;
                *iterate = (*iterate)->right;
                (*iterate)->parent = NULL;
                free(deleted);
            }

            if(direction == 'l')
            {
                node* deleted = *iterate;
                (*iterate)->parent->left = (*iterate)->right;
                free(deleted);
            }

            if(direction == 'r')
            {
                node* deleted = *iterate;
                (*iterate)->parent->right = (*iterate)->right;
                free(deleted);
            }

            return;
        }

        if((*iterate)->right == NULL)
        {
            if(direction == 't')
            {
                node* deleted = *iterate;
                *iterate = (*iterate)->left;
                (*iterate)->parent = NULL;
                free(deleted);
            }

            if(direction == 'l')
            {
                node* deleted = *iterate;
                (*iterate)->parent->left = (*iterate)->left;
                free(deleted);
            }

            if(direction == 'r')
            {
                node* deleted = *iterate;
                (*iterate)->parent->right = (*iterate)->left;
                free(deleted);
            }

            return;
        }

        node* findmin = (*iterate)->right;

        int minVal = 0;

        while(findmin != NULL)
        {
            minVal = findmin->val;
            findmin = findmin->left;
        }

        (*iterate)->val = minVal;

        del(&((*iterate)->right), minVal, 'r');

        return;
    }

    if(newVal < (*iterate)->val)
        del(&((*iterate)->left) ,newVal, 'l');
    else
        del(&((*iterate)->right) ,newVal, 'r');

}


void insert_node(node** iterate, int newVal, node* newParent)
{
    if(*iterate == NULL)
    {
        node* newNode = (node*)malloc(sizeof(node));

        newNode->val = newVal;
        newNode->left = NULL;
        newNode->right = NULL;
        newNode->parent = newParent;

        *iterate = newNode;

        return;
    }

    if(newVal < (*iterate)->val)
        insert_node(&((*iterate)->left) , newVal, *iterate);
    else
        insert_node(&((*iterate)->right) , newVal, *iterate);
}

int main()
{
    node* iterate = NULL;

    insert_node(&iterate, 8, NULL);
    insert_node(&iterate, 15, NULL);
    insert_node(&iterate, 4, NULL);
    insert_node(&iterate, 2, NULL);
    insert_node(&iterate, 1, NULL);
    insert_node(&iterate, 3, NULL);
    insert_node(&iterate, 7, NULL);
    insert_node(&iterate, 6, NULL);
    insert_node(&iterate, 11, NULL);
    insert_node(&iterate, 22, NULL);
    insert_node(&iterate, 12, NULL);
    insert_node(&iterate, 13, NULL);    


    traverse(iterate);
    printf("\n\n");

    del(&iterate, 8, 't');
    del(&iterate, 22, 't');
    del(&iterate, 7, 't');
    del(&iterate, 11, 't');

    printf("\n\n");
    traverse(iterate);

    cin.clear();
    cin.ignore(255, '\n');
    cin.get(); 

}

Thank you for your help 谢谢您的帮助

Your problem is when you delete a node you set the child node pointer of the deleted parent to the deleted node's child, but you don't set the deleted parent's child pointer to the deleted node's child. 您的问题是,当您删除节点时,会将已删除的父级的子节点指针设置为已删除节点的子级,但不会将已删除的父级的子指针设置为已删除节点的子级。

For instance: 例如:

    if(direction == 'l')
    {
        node* deleted = *iterate;
        (*iterate)->parent->left = (*iterate)->right;
        deleted->right->parent = deleted->parent;
        free(deleted);
    }

You were missing the line deleted->right->parent = deleted->parent; 您错过了以下行: deleted->right->parent = deleted->parent; , I added it. ,我添加了它。 There are a few more places in the code you should fix in the same manner. 您应该以相同的方式修复代码中的其他几个地方。

Your problem is that you don't update the parents when you delete a node with children. 您的问题是,删除带有子节点的节点时不会更新父节点。 The parent field is only assigned when you insert a node, and hence you have a well-defined tree. 仅当您插入节点时才分配parent字段,因此您具有定义良好的树。 You also set it in some cases, eg when there is only one child and the direction is 't' . 在某些情况下,例如在只有一个孩子且方向为't'情况下,也可以进行设置。

You break the tree when you start jiggling around nodes without updating the parents of the children of the deleted nodes in the 'l' and 'r' cases. 当您开始在节点之间摇摆时,如果不更新被删除节点的子节点的父节点(在'l''r'情况下),则会破坏树。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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