此代码:
删除是问题所在,我已经自己完成了这段代码(所以这可能不是常规方法)。我将删除分为三个部分进行检查:
这个程序的每个部分都运行相关的、正确的输出(只是一切!),除非root是唯一剩下的节点并且我们正在尝试删除root。
它进入nonode函数(在函数中有root的特殊情况),甚至打印“您已删除内存中唯一的节点”。一旦选择任何选项again.however显示错误,就会给出所有选项。例如,在尝试打印各种遍历时,它会在检查遍历时打印无限的地址列表,最终. exe文件会停止,而不是打印“内存中没有二叉树”。
#include <stdio.h>
#include <stdlib.h>
struct bt
{
struct bt *left;
int data;
struct bt *right;
};
struct bt *root=NULL,**sp=NULL;
void insertion(struct bt**,int);
void prtraversal(struct bt**);
void intraversal(struct bt**);
void potraversal(struct bt**);
void search(struct bt**,int);
void del(struct bt **n,int key);
void nonode(struct bt **n);
void onenode(struct bt **n);
void bothnode(struct bt **n);
main()
{
int ch,key;
printf("******\n\n The program automatically avoids inclusion of repeat numbers\n\n**********");
while(1)
{
printf("\nenter your choice\n1 for insertion\n2 for search\n3 for Various Traversal\n4 for deletion\n5 for exit\n");
scanf("%d",&ch);
switch(ch)
{
case 1:
printf("Enter your Key for insertion\n");
scanf("%d",&key);
insertion(&root,key);
break;
case 2:
if(root!=NULL)
{
printf("Enter your Key for search\n");
scanf("%d",&key);
search(&root,key);
}
else
{
printf("\n NO BINARY TREE IN MEMORY\n");
}
break;
case 3:
if(root!=NULL)
{
printf("\n\nPREORDER TRAVERSAL:");
prtraversal(&root);
printf("\n\nINORDER TRAVERSAL:");
intraversal(&root);
printf("\n\nPOSTORDER TRAVERSAL:");
potraversal(&root);
}
else
{
printf("\n NO BINARY TREE IN MEMORY\n");
}
break;
case 4:
if(root!=NULL)
{
printf("Enter your Key for Delete\n");
scanf("%d",&key);
del(&root,key);
}
else
{
printf("\n NO BINARY TREE IN MEMORY\n");
}
break;
case 5:
exit(1);
default:
printf("\n Wrong Choice\n");
}
sp=NULL;
}
}
void del(struct bt **n,int key)
{
if((*n)!=NULL)
{
if(key<(*n)->data)
del(&((*n)->left),key);
else if(key>(*n)->data)
del(&((*n)->right),key);
else if(key==(*n)->data)
{
printf("\nELEMENT FOUND\n");
printf("\n DELETION UNDERWAY\n");
sp=n;
if(((*n)->right)!=NULL && ((*n)->left)!=NULL)
{
bothnode(&((*n)->left));
}
else if(((*n)->right)!=NULL && ((*n)->left)==NULL)
{
onenode(&((*n)->right));
}
else if(((*n)->left)!=NULL && ((*n)->right)==NULL)
{
onenode(&((*n)->left));
}
else if(((*n)->left)==NULL && ((*n)->right)==NULL)
{
nonode(&root);
}
}
}
else
{
printf("\nELEMENT NOT FOUND\n");
}
}
void nonode(struct bt **n) //deletes the target node without any child,root address is provided to struct bt **n
{
struct bt **parent=n;//stores address of node just before target node,will be updated in this function
if(sp!=&root)//target node address stored in sp from a previous function
{
while((*n)->data!=(*sp)->data)//to find address of node just before target node and store it in struct bt **parent
{
parent=n;//frequent parent update as struct bt **n traverses tree
if(((*sp)->data)<((*n)->data))
n=&((*n)->left);
if(((*sp)->data)>((*n)->data))
n=&((*n)->right);
}
if((*parent)->right==(*sp))//checks if parent's right contains address of target node
{
(*parent)->right=NULL;
free(*sp);
}
else if((*parent)->left==(*n))//else checks if parent's left contains address of target node
{
(*parent)->left=NULL;
free(*n);
}
}
else if(sp==&root)//if the root node has to be deleted,no child on either side,only one node in tree
{
free(*sp);
printf("\nYOU DELETED THE ONLY NODE IN MEMORY\n");
}
}
删除后忘记将根设置为NULL:
else if(sp==&root)
{
free(*sp);
*sp = NULL; // <-- add this line
printf("\nYOU DELETED THE ONLY NODE IN MEMORY\n");
}
从树中删除单个节点时,您没有将root设置为NULL。因为根是全局的,所以可以在del(struct bt**n,int key)中将其设置为NULL。当您到达此支票时:
else if(((*n)->left)==NULL && ((*n)->right)==NULL)
您已经知道要删除根节点,因为之前的条件已经用尽了所有其他可能性。所以您可以简单地释放根节点并将其设置为NULL
else
{
free(*n);
*n = NULL;
}
另一方面,您的删除算法非常复杂。要删除BST中的节点,只需将其键替换为左子树中最大节点的键或右子树中最小节点的键,然后删除替换的节点。
您发布的代码在删除叶节点的函数中有缺陷。假设叶节点是根节点。可能是,但这不是重点。
这是:
else if(((*n)->left)==NULL && ((*n)->right)==NULL)
{
nonode(&root);
}
应该简单地这样做:
else nonode(n);
原因:您已经检查了前两个条件,您已经知道此指针没有chidden。实际上,甚至不需要nonode()。您可以简单地执行以下操作:
else
{
free(*n);
*n = NULL;
}
按地址传入指针的关键在于您有权修改它们。那么就这么做吧。正在删除此节点,您有引用它的指针的地址。删除节点并将该指针设置为NULL。如果该指针恰好是根,那么就这样吧;当函数完成时,它将为NULL。
关于各种扫描仪方法的工作原理,我肯定遗漏了一些明显的东西,但这真的没有任何意义: 此代码导致无限循环: 虽然此代码有效: 这是来自Oracle的文档,我不确定它是否适用或它的含义:“此方法可能会在等待扫描输入时阻塞,即使之前调用hasNext()返回true也是如此。”(http://docs.oracle.com/javase/1.5.0/docs/api/java/util/Scanner.h
在二元搜索树的情况下,为什么我们不能简单地在一个节点有两个子节点的情况下,将一个节点的前一个节点替换为后一个节点?
我在做作业,实现自己的二叉查找树。问题是,我们有自己的节点实现,它的父节点是不可直接访问的。 我一直在寻找答案,但我不想完全照搬解决方案,尽管如此,我似乎仍然没有得到正确的答案。我错过了一些元素没有被删除的情况。 你能帮帮我吗?我做错了什么? 这是删除方法: 节点使用通用接口 只有比较的方法。它看起来像这样 我在remove中使用了另一种方法,它设置节点的父节点的子节点,具体取决于它的左子节点还是
我正在尝试删除我的二叉查找树的根,以便我可以更新它的值,但这种方法不能做到这一点。我的想法是删除根,然后将其再次插入二叉查找树中,但使用另一个值。它适用于树中的每个节点,但不是我无法删除它的根本原因。有人知道为什么会发生这种情况吗?谢谢。 这是我调用方法删除任何节点的主代码,在这种情况下,我想删除根。
我试着删除二叉查找树的节点,当我打印出来的时候,我得到的结果实际上不是这个删除,实际上可以删除二叉树本身的任何键。 我是二进制搜索树的新手。有人能帮我写代码吗?我们将感谢您的帮助。 谢谢 完整代码
我试图通过这个链接BinarySearchTree来理解BST。但我在其他部分感到困惑 我不能理解其他部分,其中左大部分节点的右子树被找到,然后分配到该节点。但在这里,该节点都不为空,并且返回右节点,这对我来说是没有意义的。我希望这是一个正确的实现。有人能帮我了解一下这里发生了什么吗。