二叉搜索树删除功能两次删除相同的东西
Posted
技术标签:
【中文标题】二叉搜索树删除功能两次删除相同的东西【英文标题】:binary search tree delete function deleting the same thing twice 【发布时间】:2022-01-23 05:33:32 【问题描述】:我正在尝试创建一个删除 bst 中最左边的 2 个节点的二叉搜索树。出于某种原因,我的代码删除了第一个值两次,而不是移动到下一个。
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
struct treeNode
char *word; // the string word that is stored
int origin; // position of the word in the original text input’s line 1
struct treeNode *left; // pointer for the left children of the node
struct treeNode *right; // pointer for the right children of the node
struct treeNode *parent; // pointer for the parent of the node
;
typedef struct treeNode NODE;
NODE *
addNode(NODE * r, char *x)
// r = root pointer of the tree
// x = value to add into this tree
// return the root of the updated tree
NODE *p = malloc(sizeof(NODE));
p->word = malloc(strlen(x) + 1);
strcpy(p->word, x); // strcpy input: (destination, data to be copied)
// printf("%s", x);
p->parent = NULL;
p->left = NULL;
p->right = NULL;
// if tree is empty, tree consists of p only
if (r == NULL)
return p;
if (strcmp(x, r->word) > 0)
r->right = addNode((r->right), x);
return r;
else
// add new node the left subtree
r->left = addNode((r->left), x);
return r;
return r;
NODE *
getLeftMostNode(NODE * root)
// return the pointer to the right most node
if (root == NULL)
return NULL;
NODE *p = root;
while (p->left != NULL)
p = p->left;
return p;
NODE *
addTree2Tree(NODE * X, NODE * Y)
if (X == NULL)
return Y;
if (Y == NULL)
return X;
X = addNode(X, Y->word);
X = addTree2Tree(X, Y->left);
X = addTree2Tree(X, Y->right);
return X;
NODE *
removeNode(NODE * r)
// remove any node that store value x from tree
// r: root pointer of this tree
// return root pointer of the updated tree after removal
NODE *p = getLeftMostNode(r);
NODE *C = p->parent;
NODE *A = p->left;
NODE *B = p->right;
if (C == NULL)
// p is root of the tree
free(p);
return addTree2Tree(A, B); // add tree A and tree B and return the new combination tree
if (A != NULL)
// make A a child of C assuming position of P
if (p == C->left)
C->left = A;
else
C->right = A;
A->parent = C;
free(p);
return addTree2Tree(r, B);
if (B != NULL)
if (p == C->left)
C->left = B;
else
C->right = B;
B->parent = C;
free(p);
return r;
if (p == C->left)
C->left = NULL;
else
C->right = NULL;
free(p); // free allocation for p
return r;
void
printArray(NODE * r)
// print all the values on the tree rooted at node "r" // print in alphabetical order
// if the tree is empty, return // print all the values on the tree rooted at node "r" // print in the in-order order: print left first, followed by root, followed by right values
if (r == NULL)
return;
else
printArray(r->left); // print all values in left subtree
printf("%s ", r->word);
printArray(r->right); // print all values in right subtree
int
main()
// input must be implemented by linked list, not array
NODE *root = NULL;
int ch;
char in[1000]; // input array
int len = 0;
char del[100]; // word to be deleted
char word[1000];
while ((ch = getchar()) != '\n')
in[len++] = ch;
in[len] = '\0';
// printf("%s\n", in);
int i = 0,
j = 0;
while (i <= len)
// space to store a word
if ((in[i] == ' ') || (in[i] == '\0') || (in[i] == '\t'))
word[j] = '\0'; // end of word
j = 0;
root = addNode(root, word);
// printf("%s\n", word);
else
word[j++] = in[I];
i++;
int k = 0;
removeNode(root);
removeNode(root);
printArray(root);
printf("\n");
return 0;
这是我得到的错误
【问题讨论】:
为什么addNode会递归分配多个节点然后泄露? 即使不看removeNode
,我们也可以看出removeNode(root);
显然是错误的。如果树中只剩下一个节点怎么办? root
需要修改。
提示:p->word = malloc(strlen(x) + 1); strcpy(p->word, x);
可以简化为p->word = strdup(x);
【参考方案1】:
函数removeNode
正在寻找parent
,但parent
从未在addNode
中分配。你想分配r->right->parent = r;
和r->left->parent = r;
。
BST 不保留重复键。如果strcmp(x, r->word) == 0
,则不要添加新节点。
addNode
也应该更正,如果r
是NULL
,函数会立即返回新节点。
NODE* addNode(NODE* r, char* x)
if(!x)
return NULL;
if (!r)
NODE* p = malloc(sizeof(NODE)); if (!p) return NULL;
p->word = strdup(x);
p->parent = NULL;
p->left = NULL;
p->right = NULL;
return p;
if (strcmp(x, r->word) > 0)
r->right = addNode((r->right), x);
r->right->parent = r;
return r;
else if (strcmp(x, r->word) < 0)
r->left = addNode((r->left), x);
r->left->parent = r;
return r;
return r;
修改插入函数,使root
只分配一次:
while (i <= len)
if ((in[i] == ' ') || (in[i] == '\0') || (in[i] == '\t'))
word[j] = '\0';
j = 0;
if(!root)
root = addNode(root, word);
else
addNode(root, word);
else
word[j++] = in[i];
i++;
仔细检查指针以确保避免使用NULL
指针。例如:
NODE* removeNode(NODE* r)
if(!r)
return NULL;
NODE* p = getLeftMostNode(r);
if(!p)
return NULL;
...
我尚未检查其余代码,但该示例将适用于所做的这些更改。
【讨论】:
以上是关于二叉搜索树删除功能两次删除相同的东西的主要内容,如果未能解决你的问题,请参考以下文章
C++-二叉搜索树的查找&插入&删除-二叉搜索树代码实现-二叉搜索树性能分析及解决方案
⭐算法入门⭐《二叉树 - 二叉搜索树》中等05 —— LeetCode 450. 删除二叉搜索树中的节点