如何解决如何删除二叉搜索树中的重复项?
我正在尝试编写一个函数来删除二叉搜索树中的冗余项。我完全被困住了。谁能帮我?任何帮助,将不胜感激。 (C程序)
解决方法
正如@Jack Lilhammers 在评论中指出的那样,创建新的空树并将其从原始树中插入节点会很好......你可以这样做。
- 创建一个空的二叉搜索树。
- 提取原
bst
的根节点,如果新树中不存在,则将其插入到T
中 - 删除你原来的
bst
的根节点 - 递归地执行步骤 2-3,直到原始树中没有节点
让我们实施所需的程序来创建一个完整的工作程序。首先包括工作所需的库
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
节点结构将
typedef struct node{
int key;
struct node *left,*right,*parent;
}BST;
首先我们需要实现create_empty_bst
过程
BST create_empty_bst(void){
BST* root = NULL;
return root;
}
要插入提取的根节点,我们需要 insert
函数。它的返回值可以是 void
或 BST
,这完全取决于我们。如果我们使用 void
返回类型,那么函数需要获取指向树根的指针(又名双指针);否则,我们可以传递指向树根的指针,并返回树的根。你可以做任何一种方式。我会用第二个
BST*new_Node(int data){
BST* node = (BST*)malloc(sizeof(struct node));
assert(node != NULL); // or you can write if(node == NULL) printf("error"); exit(0);
node->key = data;
node->left = node->right = node->parent = NULL; // node is inserted always at leaf. so pointers are NULL
return node;
}
void insert(BST** root,int x) {
BST* node = new_Node(x);
BST* p = NULL,* y = *root;
while (y != NULL) {
p = y;
if (y->key == x)
return;
if (y->key > node->key)
y = y->left;
else
y = y->right;
}
node->parent = p;
if (p == NULL)
*root = node;
else if (p->key > node->key)
p->left = node;
else
p->right = node;
}
New_Node(x)
创建具有适当属性的节点。对 insert
函数的唯一添加是:
if(y->key == x)
return;
当 y->key == x
时,我们遇到了重复值。我们不会再进一步并终止程序。通过使用此 if
,我们可以防止将重复值插入到新树中。
程序中最复杂和最耗时的部分是 DELETE
过程。我们需要执行其他 4 个程序才能完成删除。这 4 个过程是:SEARCH(BST*root,int x)
、SUCCESSOR(BST* node)
、find_min(BST* node)
和 TRANSPLANT(BST* root,BST* u,BST* v)
。如果理解DELETE
有困难,可以查看CLRS中的二叉搜索树(第12章)。我从这本书中得到了这个 DELETE
。这5个程序的实现如下:
BST* TRANSPLANT(BST* root,BST* v) {
if (u->parent == NULL)
root = v;
else if (u->parent->left == u)
u->parent->left = v;
else
u->parent->right = v;
if (v != NULL)
v->parent = u->parent;
return root;
}
BST* find_min(BST* node) {
if (node == NULL)
return node;
while (node->left)
node = node->left;
return node;
}
find_min(node)
查找以节点 node
为根的子树上的最小元素(如果有)。
BST* SUCCESSOR(BST* node) {
if (node == NULL)
return node;
if (node->right != NULL)
return find_min(node->right);
while (node->parent != NULL && node->parent->right == node)
node = node->parent;
return node->parent;
}
SUCCESSOR(node)
在以节点 node->key
为根的子树中查找下一个大于 node
的元素(如果有)。
BST* SEARCH(BST* N,int x) {
if (N == NULL || N->key == x)
return N;
else if (N->key > x)
return SEARCH(N->left,x);
else
return SEARCH(N->right,x);
}
BST* DELETE(BST* root,int x) {
BST* node = SEARCH(root,x);
assert(node != NULL);
BST* bosh = root;
if (node->right == NULL) {
root = TRANSPLANT(bosh,node,node->left);
}
else if (node->left == NULL) {
root = TRANSPLANT(bosh,node->right);
}
else {
BST* temp = SUCCESSOR(node);
if (node->right != temp) {
root = TRANSPLANT(root,temp,temp->right);
temp->right = node->right;
temp->right->parent = temp;
}
root = TRANSPLANT(root,temp);
temp->left = node->left;
temp->left->parent = temp;
}
return root;
}
我们必须执行 DELETE_DUPLICATES(BST* new_tree,BST* original)
程序。
BST* DELETE_DUPLICATES(BST* new_tree,BST* original) {
while (original) {
insert(&new_tree,original->key);
original = DELETE(original,original->key);
}
return new_tree;
}
我们完成了。为了测试,我将编写整个程序,以便您轻松查看所有过程。
下面是整个程序,而不是上面实现的单独程序。
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
typedef struct node {
int key;
struct node* left,* right,* parent;
}BST;
void preorder(BST*);
BST* DELETE_DUPLICATES(BST*,BST*);
void display_tree(BST*);
BST* create_empty_bst(void);
BST* new_Node(int);
void insert(BST**,int);
BST* insertSimple(BST*,int);
BST* TRANSPLANT(BST*,BST*,BST*);
BST* SUCCESSOR(BST*);
BST* find_min(BST* );
BST* SEARCH(BST*,int);
BST* DELETE(BST*,int);
BST* create_empty_bst(void) {
BST* root = NULL;
return root;
}
BST* new_Node(int data) {
BST* node = (BST*)malloc(sizeof(struct node));
assert(node != NULL); // or you can write if(node == NULL) printf("error"); exit(0);
node->key = data;
node->left = node->right = node->parent = NULL; // node is inserted always at leaf. so pointers are NULL
return node;
}
void insert(BST** root,* y = *root;
while (y != NULL) {
p = y;
if (y->key == x)
return;
if (y->key > node->key)
y = y->left;
else
y = y->right;
}
node->parent = p;
if (p == NULL)
*root = node;
else if (p->key > node->key)
p->left = node;
else
p->right = node;
}
BST* insertSimple(BST* root,* y = root;
while (y != NULL) {
p = y;
if (y->key > node->key)
y = y->left;
else
y = y->right;
}
node->parent = p;
if (p == NULL)
root = node;
else if (p->key > node->key)
p->left = node;
else
p->right = node;
return root;
}
BST* TRANSPLANT(BST* root,BST* v) {
if (u->parent == NULL)
root = v;
else if (u->parent->left == u)
u->parent->left = v;
else
u->parent->right = v;
if (v != NULL)
v->parent = u->parent;
return root;
}
BST* find_min(BST* node) {
if (node == NULL)
return node;
while (node->left)
node = node->left;
return node;
}
BST* SUCCESSOR(BST* node) {
if (node == NULL)
return node;
if (node->right != NULL)
return find_min(node->right);
while (node->parent != NULL && node->parent->right == node)
node = node->parent;
return node->parent;
}
BST* SEARCH(BST* N,temp);
temp->left = node->left;
temp->left->parent = temp;
}
return root;
}
void preorder(BST* root) {
if (root) {
printf("%d ",root->key);
preorder(root->left);
preorder(root->right);
}
}
void display_tree(BST* root) {
preorder(root);
printf("\n");
}
BST* DELETE_DUPLICATES(BST* new_tree,original->key);
}
return new_tree;
}
int main(void) {
BST* new_tree = NULL,* original = NUL;
original = insertSimple(original,20); original = insertSimple(original,20);
original = insertSimple(original,12);
original = insertSimple(original,30);
original = insertSimple(original,18);
original = insertSimple(original,11);
display_tree(original);
display_tree(new_tree);
new_tree = DELETE_DUPLICATES(new_tree,original);
display_tree(new_tree);
return 0;
}
注意: insertSimple
函数将元素插入到 original
树中。我们不能使用 insert
过程,因为它不会插入重复的元素。 insertSimple
过程就是为此目的编写的。 preorder
过程打印预订单中的元素。 (如果有困难,看preorder traversal
)。就是这样,祝你工作顺利。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。