- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我的二叉搜索树程序即将完成。但是,我坚持删除:删除具有左右子树的节点。最大的左值在左子树中提升。它有时会起作用,但并不总是按应有的方式起作用。即,如果您将值 23、14、31、7、9 输入到树中并删除 23,则得出的值是 14 14 7 9。请帮忙!
#include <stdio.h>
#include <stdlib.h>
typedef struct node {
int key;
struct node* left;
struct node* right;
}node;
struct node* root= NULL;
int count=0;
void preOrder(node* temp){
if (temp!=NULL){
printf("%d ",temp->key);
preOrder(temp->left);
preOrder(temp->right);
}
}
//for printing
void inOrder(node* temp){
if (temp!=NULL){
inOrder(temp->left);
printf("%d ",temp->key);
inOrder(temp->right);
}
}
void printPrompt(void){
int choice=-1;
do{
printf(" Enter <1> Inorder <2> Preorder <3> Return to Menu: ");
scanf("%d", &choice);
if(choice!=1 && choice!=2 && choice!=3) printf(" Error: invalid input! \n\n");
if(choice==1){
if(root==NULL) printf("\tError: is empty tree\n");
else {
printf("\tInorder:\t ");
inOrder(root);
printf("\n\n");
}
}
else if (choice==2){
struct node* temp=root;
if(root==NULL) printf("\tError: is empty tree\n");
else {
printf("\tPreorder:\t ");
preOrder(root);
printf("\n\n");
}
}
}while (choice!=3);
printf(" <Exit print method>\n\n");
}
//printing complete
//both are similar code- one searches and another finds the node
int contains(node* current, int value){
if(current==NULL) return 0;
if (value==current->key) {
return 1;
}
else if(value < current->key) return contains(current->left, value);
else return contains(current->right, value);
}
node* findParent(node* current, int value){
if (value == current->key) return NULL; //if only one node in BST, then no parent node
if (value < current->key) {
if (current->left == NULL) return NULL; //if value not found, return null
else if (current->left->key == value) return current;
else return findParent (current->left, value);
}
else {
if (current->right == NULL) return NULL;
else if (current->right->key== value) return current;
else return findParent (current->right, value);
}
}
node* findNode(node* current, int value){
if (current == NULL) return NULL;
if (current->key == value) {
return current;
}
else if (value < current->key) return findNode (current->left, value);
else return findNode (current->right, value);
}
//
void del(value){
struct node* nodeToRemove= findNode(root, value);
if (nodeToRemove == NULL) printf("\tError: node not found in tree\n");
else {
struct node* parent = findParent(root, value);
if (count == 1 ) {
root= NULL;
printf("\tRemoving the only node in BST\n");
}
else if (nodeToRemove->left == NULL && nodeToRemove->right == NULL){
printf("\tRemoving leaf node in BST\n");
if (nodeToRemove->key < parent->key) parent->left = NULL;
else parent->right = NULL;
}
else if (nodeToRemove->left== NULL && nodeToRemove->right != NULL){
printf("\tRemoving node with right subtree but no left subtree\n");
if (nodeToRemove->key < parent->key) {
parent->left = nodeToRemove->right;
}
else parent->right = nodeToRemove->right;
}
else if (nodeToRemove->left!= NULL && nodeToRemove->right == NULL){
printf("\tRemoving node with left subtree but no right subtree\n");
if (nodeToRemove->key < parent->key) {
parent->left = nodeToRemove->left;
}
else parent->right = nodeToRemove->left;
}
else{
printf("\tRemoving node with both left subtree and right subtree\n");
struct node* nodeLargestLeft = nodeToRemove -> left;
while (nodeLargestLeft -> right != NULL) nodeLargestLeft= nodeLargestLeft->right;
findParent(root, nodeLargestLeft->key)->right=NULL;
nodeToRemove->key=nodeLargestLeft->key;
}
}
printf("\tResult: ");
preOrder(root);
printf("\n");
count= count-1;
}
void deletePrompt(void){
int value=-1;
do{
printf(" Delete key or press -1 to return to menu: ");
scanf("%d", &value);
if(value>0){
if(root==NULL) printf("\tError: is empty tree\n");
else del(value);
}
else if (value<=0) printf("\tError: key not positive\n");
}while (value!=-1);
printf(" <Exit delete method>\n\n");
}
void searchPrompt(void){
int value=-1;
do{
printf(" Search key or press -1 to return to menu: ");
scanf("%d", &value);
if(value>0){
if (root==NULL) printf("\tError: tree is empty\n");
else {
if(contains(root, value)) printf("\tKey %d is found\n",value);
else printf("\tKey %d is not found\n",value);
}
}
else if (value<=0) printf("\tError: key not positive\n");
}while (value!=-1);
printf(" <Exit search method>\n\n");
}
//for search
//for insertion
void insertNode(node* current, int value){
if(value< current->key){
if (current->left == NULL) {
current->left=(node*) malloc(sizeof(node));
current->left->key = value;
current->left->left = NULL;
current->left->right = NULL;
printf("\tSuccess! Value inserted: %d\n", current->left->key);
}
else {
insertNode(current->left, value);
}
}
else {
if (current->right == NULL) {
current->right=(node*) malloc(sizeof(node));
current->right->key = value;
current->right->left = NULL;
current->right->right = NULL;
printf("\tSuccess! Value inserted: %d\n", current->right->key);
}
else {
insertNode(current->right, value);
}
}
}//end insert
void insert(int value){
if(root==NULL){ //empty tree
root =(node*) malloc(sizeof(node));
root->key= value;
printf("\tPrint root here: %d\n", value);
root->left= NULL;
root->right=NULL;
printf("\tSuccess! Value inserted: %d\n", root->key);
}
else {
insertNode(root, value);
}
printf("\tResult: ");
preOrder(root);
printf("\n");
}
void insertPrompt(void){
int value=-1;
do{
printf(" Insert value or press -1 to return to menu: ");
scanf("%d", &value);
if(value>0){
insert(value);
count= count+1;
printf("\tCount: %d\n", count);
}
else if (value<=0)printf("\tError: key not positive\n");
}while (value!=-1);
printf(" <Exit insert method>\n\n");
}
int menuPrompt(void){
int choice=-1;
do{
printf("Enter <1> Search <2> Insert <3> Delete <4> Print Tree <5> Quit: ");
scanf("%d", &choice);
if(choice>5 || choice<1) printf("Error: invalid input! \n\n");
} while(choice>5 || choice<1);
return choice;
}
int main(int argc, char *argv[]){
int choice=-1;
int value=-1;
while(choice!=5){
choice=menuPrompt();
switch(choice){
case 1:
searchPrompt();
break;
case 2:
insertPrompt();
break;
case 3:
deletePrompt();
break;
case 4:
printPrompt();
break;
case 5:
printf("<Exit program> \n");
break;
}//end switch
}
system("PAUSE");
return 0;
}
最佳答案
您对具有两个子树的节点的删除算法略有错误。你正确地做的是:
求左子树的最大值(或右子树的最小值):
struct node* nodeLargestLeft = nodeToRemove -> left;
while (nodeLargestLeft -> right != NULL)
nodeLargestLeft= nodeLargestLeft->right;
将要移除的节点的值替换为上面找到的节点的值
nodeToRemove->key=nodeLargestLeft->key;
您尝试从示例树中删除 23
23
/ \
14 31
/
7
\
9
它在左子树中有 14 个最大值,现在看起来像这样:
14
/ \
14 31
/
7
\
9
但是现在,您不能只删除最大节点(即您的根节点)的父节点的右子树。在您提到的示例中,这将是整个二叉树的右子树!
findParent(root, nodeLargestLeft->key)->right=NULL; // wrong
相反,您必须对重复节点(第二层中的节点 14)执行定期删除程序。因为它是左子树中具有最大值的节点,所以它不能有右子树。所以只有两种情况:要么左子树也为空,这种情况下该节点可以被丢弃,要么它被填充,这种情况下左子树的根节点替换该节点。
在你的例子中,第二种情况发生了,你的树应该看起来像这样:
14
/ \
7 31
\
9
只要进行最少的侵入性更改,此过程就可以工作:
printf("\tRemoving node with both left subtree and right subtree\n");
struct node* nodeLargestLeft = nodeToRemove->left;
parent = findParent(root, nodeLargestLeft->key);
while (nodeLargestLeft -> right != NULL) {
parent = nodeLargestLeft;
nodeLargestLeft= nodeLargestLeft->right;
}
nodeToRemove->key=nodeLargestLeft->key;
parent->left = nodeLargestLeft->left;
你的代码还有其他几个问题,例如
parent
是一个NULL
指针,导致 parent->key 出现段错误
findParent
的调用看起来很难看,最好在遍历树或为每个节点维护父指针时跟踪父节点。关于c - C中的二叉搜索树-删除具有左右子树的节点时出错,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41422920/
这是代码片段。 请说出这种用小内存存储大数据的算法是什么。 public static void main(String[] args) { long longValue = 21474836
所以我使用 imap 从 gmail 和 outlook 接收电子邮件。 Gmail 像这样编码 =?UTF-8?B?UmU6IM69zq3OvyDOtc68zrHOuc67IG5ldyBlbWFpb
很久以前就学会了 C 代码;想用 Scheme 尝试一些新的和不同的东西。我正在尝试制作一个接受两个参数并返回两者中较大者的过程,例如 (define (larger x y) (if (> x
Azure 恢复服务保管库有两个备份配置选项 - LRS 与 GRS 这是一个有关 Azure 恢复服务保管库的问题。 当其驻留区域发生故障时,如何处理启用异地冗余的恢复服务保管库?如果未为恢复服务启
说,我有以下实体: @Entity public class A { @Id @GeneratedValue private Long id; @Embedded private
我有下一个问题。 我有下一个标准: criteria.add(Restrictions.in("entity.otherEntity", getOtherEntitiesList())); 如果我的
如果这是任何类型的重复,我会提前申请,但我找不到任何可以解决我的具体问题的内容。 这是我的程序: import java.util.Random; public class CarnivalGame{
我目前正在使用golang创建一个聚合管道,在其中使用“$ or”运算符查询文档。 结果是一堆需要分组的未分组文档,这样我就可以进入下一阶段,找到两个数据集之间的交集。 然后将其用于在单独的集合中进行
是否可以在正则表达式中创建 OR 条件。 我正在尝试查找包含此类模式的文件名列表的匹配项 第一个案例 xxxxx-hello.file 或者案例二 xxxx-hello-unasigned.file
该程序只是在用户输入行数时创建菱形的形状,因此它有 6 个 for 循环; 3 个循环创建第一个三角形,3 个循环创建另一个三角形,通过这 2 个三角形和 6 个循环,我们得到了一个菱形,这是整个程序
我有一个像这样的查询字符串 www.google.com?Department=Education & Finance&Department=Health 我有这些 li 标签,它们的查询字符串是这样
我有一个带有静态构造函数的类,我用它来读取 app.config 值。如何使用不同的配置值对类进行单元测试。我正在考虑在不同的应用程序域中运行每个测试,这样我就可以为每个测试执行静态构造函数 - 但我
我正在寻找一个可以容纳多个键的容器,如果我为其中一个键值输入保留值(例如 0),它会被视为“或”搜索。 map, int > myContainer; myContainer.insert(make_
我正在为 Web 应用程序创建数据库,并正在寻找一些建议来对可能具有多种类型的单个实体进行建模,每种类型具有不同的属性。 作为示例,假设我想为“数据源”对象创建一个关系模型。所有数据源都会有一些共享属
(1) =>CREATE TABLE T1(id BIGSERIAL PRIMARY KEY, name TEXT); CREATE TABLE (2) =>INSERT INTO T1 (name)
我不确定在使用别名时如何解决不明确的列引用。 假设有两个表,a 和 b,它们都有一个 name 列。如果我加入这两个表并为结果添加别名,我不知道如何为这两个表引用 name 列。我已经尝试了一些变体,
我的查询是: select * from table where id IN (1,5,4,3,2) 我想要的与这个顺序完全相同,不是从1...5,而是从1,5,4,3,2。我怎样才能做到这一点? 最
我正在使用 C# 代码执行动态生成的 MySQL 查询。抛出异常: CREATE TABLE dump ("@employee_OID" VARCHAR(50)); "{"You have an er
我有日期 2016-03-30T23:59:59.000000+0000。我可以知道它的格式是什么吗?因为如果我使用 yyyy-MM-dd'T'HH:mm:ss.SSS,它会抛出异常 最佳答案 Sim
我有一个示例模式,它的 SQL Fiddle 如下: http://sqlfiddle.com/#!2/6816b/2 这个 fiddle 只是根据 where 子句中的条件查询示例数据库,如下所示:
我是一名优秀的程序员,十分优秀!