C++ 二元搜索树中的访问冲突读取位置0x00000000
只是显示二叉树的节点是什么样子。我不确定是什么问题,但我有一种感觉,这与函数的私密性有关。如何比较私有数据,以便查看我要查找的值是否在该节点内C++ 二元搜索树中的访问冲突读取位置0x00000000,c++,access-violation,C++,Access Violation,只是显示二叉树的节点是什么样子。我不确定是什么问题,但我有一种感觉,这与函数的私密性有关。如何比较私有数据,以便查看我要查找的值是否在该节点内 class binarytree { private: class node { public: int data; node * left; node * right; node (
class binarytree
{
private:
class node
{
public:
int data;
node * left;
node * right;
node (int x)
{
data = x;
left=NULL;
right=NULL;
}
};
node * root;
这就是插入节点的方式
void insert(int x, node * &r)
{
if(r==NULL)
{
r= new node(x);
}
else
{
if(x < r->data)
{
//insert left
insert(x, r->left);
}
else
{
//insert right
insert(x, r->right);
}
}
}
编辑:这是程序的另一个功能,它可以工作,但可能会导致r指向NULL
int extractMin(node * &r)
{
if(r->left == NULL)
{
if(r->right == NULL)
{
return r->data;
}
else
{
int x = r->data;
r = r->right;
return x;
}
}
else
{
return extractMin(r->left);
}
}
下面是检查r是否为NULL的新函数
void remove(int x, node * &r)
{
if(r == NULL)
{
cout<<"why am I null?"<<endl;
}
else
{
if(x == r->data)
{
if(r->right == NULL && r->left == NULL)
{
r = NULL;
}
else if(r->right == NULL && r->left != NULL)
{
r = r->left;
}
else if(r->right != NULL && r->left == NULL)
{
r = r->right;
}
else
{
node * temp;
temp =r;
r = r->left;
while(r->right != NULL)
{
r = r->right;
}
r->right = temp->right;
delete temp;
}
}
else if ( x < r->data)
{
remove(x, r->left);
}
else if (x > r->data)
{
remove(x , r->left);
}
}
}
void删除(int x,node*&r)
{
if(r==NULL)
{
coutright==NULL&&r->left!=NULL)
{
r=r->左;
}
如果(r->right!=NULL&&r->left==NULL),则为else
{
r=r->右;
}
其他的
{
节点*温度;
温度=r;
r=r->左;
while(r->right!=NULL)
{
r=r->右;
}
r->右侧=临时->右侧;
删除临时文件;
}
}
else if(xdata)
{
移除(x,r->左侧);
}
否则如果(x>r->数据)
{
移除(x,r->左侧);
}
}
}
如果错误是这样说的,那么当您尝试去区分它时,r指向NULL。
因此,您必须确保当您将memmory分配给r时,它不会返回NULL
binarytree()
{
root = NULL;
}
void remove(int x)
{
remove(x,root);
}
在您的例子中,当您在调用insert之前调用remove时,您试图取消差异NULL(正如错误所说的那样),这种情况会在代码中发生。
您只需在remove的开头检查r是否指向NULL。
或者更好的方法是,确保在r为NULL时不会在r中进行解析。在尝试访问内部成员之前,应始终检查
NULL
:
void remove(int x, node * &r)
{
if(r != NULL)
{
// Your code
}
}
您可以使用r
作为NULL
调用remove,然后尝试选中r.Left
。那么这里就有访问冲突了
我还要问,这对你有用吗?具体来说,insert
不会以这种方式工作。
试一试
void插入(int x,node*&r)
{
if(r==NULL)
{
r=新节点(x);
}
其他的
{
如果(x数据)
{
如果(r->left!=NULL)
{
//向左插入
插入(x,r->左);
}
其他的
{
r->左=新节点(x);
}
}
其他的
{
如果(r->右!=空)
{
//插入右侧
插入(x,r->右侧);
}
其他的
{
r->左=新节点(x);
}
}
}
}
r
以某种方式为空。您需要检查传入的r
是否为NULL
,或者检查root
是否为非NULL,并且仅当子项存在时才调用remove
。您正在将x
与root
进行比较。当树为空时,root==nullptr
。您应该首先检查r==nullptr
,如下所示:
bool remove(int x, node * &r) {
if(!r) {
return false; // Indicate whether removal succeeded
}
//... etc.
}
TL;DR(见附件)。无论如何,“访问冲突读取位置0x00000000”显然是一个空指针取消引用。请在调试器中运行程序,逐行检查
insert
函数,以确保其正常工作。如果是,则逐行执行remove
函数。似乎在remove
函数中,您需要检查r
是否为NULL
。。。如果它是。。。正如Joachim所说,当你遇到这种问题时,使用一个调试器。好的,我检查了NULL,它显示r==NULL。我的根如何为NULL?@user2782774正如我在回答中告诉你的:你在构造函数中将它设置为NULL,因此如果你在调用isnert之前调用remove,你就没有更改它。或者,如果您在没有节点的情况下调用remove,那么您也会将其设置为NULL,这可能是因为错误的循环索引或其他原因。。。你甚至不知道你自己的代码吗?@user2782774另外,我认为你的insert方法不能正常工作。除了remove函数外,代码中的所有东西都可以正常工作。我有一个名为“insert”的公共空函数,它有一个int参数。@user2782774我知道,但如果一切正常,你就不会有一个NULL作为根。。。。尝试插入和打印一些项目…我检查了,R确实为空,但我不知道当树中有项目时,这是怎么可能的。@user2782774您在未检查的情况下对子项调用remove,这就是为什么
void remove(int x, node * &r)
{
if(r != NULL)
{
// Your code
}
}
void insert(int x, node * &r)
{
if(r==NULL)
{
r= new node(x);
}
else
{
if(x < r->data)
{
if(r->left != NULL)
{
//insert left
insert(x, r->left);
}
else
{
r->left = new node(x);
}
}
else
{
if(r->right != NULL)
{
//insert right
insert(x, r->right);
}
else
{
r->left = new node(x);
}
}
}
}
bool remove(int x, node * &r) {
if(!r) {
return false; // Indicate whether removal succeeded
}
//... etc.
}