簡體   English   中英

C ++二進制搜索樹刪除問題

[英]C++ Binary search tree delete issue

我是C ++的新手。 我的背景來自PHP和C#。 我在Visual Studio 2005中的VC ++中實現了二進制搜索樹

所有操作都很好,在一種特定的情況下,即當我嘗試刪除head兩次或多次時,我面臨着刪除的問題。

建議的策略是

  1. 在右邊的子樹中找到最小值
  2. 用最少的數量替換要刪除的節點
  3. 刪除最小值

在我的代碼8中位於頂部,當我第一次刪除top時,從右側子樹中刪除11成為top,如果我刪除任何其他節點,代碼工作正常,但是如果我再次刪除top(現在刪除8之后是11)我收到以下錯誤

Windows已在BinarySearchTreeByList.exe中觸發了一個斷點。

這可能是由於堆損壞所致,並表明> BinarySearchTreeByList.exe或其已加載的任何DLL中存在錯誤。

輸出窗口可能包含更多診斷信息

以下是完整的代碼

#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(); 

}

謝謝您的幫助

您的問題是,當您刪除節點時,會將已刪除的父級的子節點指針設置為已刪除節點的子級,但不會將已刪除的父級的子指針設置為已刪除節點的子級。

例如:

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

您錯過了以下行: deleted->right->parent = deleted->parent; ,我添加了它。 您應該以相同的方式修復代碼中的其他幾個地方。

您的問題是,刪除帶有子節點的節點時不會更新父節點。 僅當您插入節點時才分配parent字段,因此您具有定義良好的樹。 在某些情況下,例如在只有一個孩子且方向為't'情況下,也可以進行設置。

當您開始在節點之間搖擺時,如果不更新被刪除節點的子節點的父節點(在'l''r'情況下),則會破壞樹。

暫無
暫無

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

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