[英]C++ Binary search tree delete issue
我是C ++的新手。 我的背景來自PHP和C#。 我在Visual Studio 2005中的VC ++中實現了二進制搜索樹
所有操作都很好,在一種特定的情況下,即當我嘗試刪除head兩次或多次時,我面臨着刪除的問題。
建議的策略是
- 在右邊的子樹中找到最小值
- 用最少的數量替換要刪除的節點
- 刪除最小值
在我的代碼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.