我正在尝试实现一个用于学习目的的二叉树。当我第一次收到错误时,我想我可能删除了一个节点两次。然后我意识到即使是 print 语句也会触发断点。整个程序的其他地方都没有删除,所以问题一定出在这里。
这里是BinaryTree.cpp
#include "BinaryTree.h"
#include<iostream>
BinaryTree::BinaryTree(void):root(nullptr){}
BinaryTree::~BinaryTree(void){removeWithChildren(root);}
void BinaryTree::insert(Node *n){
cout<<"\nInserting: "<<(void*)n;
Node *y = nullptr;
Node *x = root;
while(x != nullptr){
y = x;
if(n->key < x->key)
x = x->left;
else
x = x->right;
}
n->parent = y;
if(y == nullptr)
root = n;
else if (n->key < y->key)
y->left = n;
else
y->right = n;
}
void BinaryTree::removeWithChildren(Node *n){
//forgetChild(n);
if(n->left)
removeWithChildren(n->left);
if(n->right)
removeWithChildren(n->right);
cout<<"\nDeleting: "<<(void*)n;
delete n;
}
void BinaryTree::remove(Node *n){
if(n->left == nullptr) {
transplant(n,n->right);
} else if(n->right == nullptr) {
transplant(n,n->left);
} else {
Node *y = minimum(n->right);
if(y->parent != n){
transplant(y,y->right);
y->right = n->right;
y->left = n->left;
}
transplant(n,y);
y->left = n->left;
y->left->parent = y;
}
cout<<"\nDeleting: "<<(void*)n;
delete n;
}
void BinaryTree::transplant(Node *u,Node *v){
if(u->parent == nullptr) root = v;
else if (u == u->parent->left) u->parent->left = v;
else u->parent->right = v;
if(v) v->parent == u->parent;
}
string BinaryTree::prewalk(Node *n){
string output = "";
if(n!=nullptr){
output += prewalk(n->left);
output += prewalk(n->right);
output += to_string(n->key);
}
return output;
}
string BinaryTree::inwalk(Node *n){
string output = "";
if(n!=nullptr){
output += inwalk(n->left);
output += to_string(n->key);
output += inwalk(n->right);
}
return output;
}
Node* BinaryTree::search(Node *sub_tree,int key){
if(sub_tree == nullptr) return nullptr;
if(sub_tree->key == key) return sub_tree;
if(sub_tree->key < key) return search(sub_tree->right,key);
else return search(sub_tree->left,key);
}
Node* BinaryTree::getSuccessor(Node *n){
if(n->right)
return minimum(n->right);
Node *y = n->parent;
while(y){
if(n != y->right) break;
n = y;
y = y -> parent;
}
return y;
}
Node* BinaryTree::minimum(Node *sub_tree){
while(sub_tree->left)
sub_tree = sub_tree ->left;
return sub_tree;
}
Node* BinaryTree::maximum(Node *sub_tree){
while(sub_tree->right)
sub_tree = sub_tree ->right;
return sub_tree;
}
void BinaryTree::forgetChild(Node *n){
if(n->parent){
if(n == n->parent->left) n->parent->left = nullptr;
else n->parent->right = nullptr;
}
}
这是main.cpp
#include"BinaryTree.h"
#include<iostream>
#include<random>
using namespace std;
int main(){
{
BinaryTree bt;
bt.insert(new Node(5));
bt.insert(new Node(1));
bt.insert(new Node(3));
bt.insert(new Node(4));
bt.insert(new Node(9));
//cout<<bt.inwalk(bt.getRoot())<<endl;
bt.remove(bt.search(bt.getRoot(),3));
//cout<<bt.inwalk(bt.getRoot())<<endl;
}
char x;cin>>x;
return 0;
}
这里是BinaryTree.h
#pragma once
#include<string>
using namespace std;
struct Node{
Node *left,*right,*parent;
int key;
Node():left(nullptr),right(nullptr),parent(nullptr),key(0) {}
Node(int x):left(nullptr),right(nullptr),parent(nullptr),key(x) {}
};
class BinaryTree
{
private:
Node *root;
public:
BinaryTree(void);
~BinaryTree(void);
Node* getRoot() { return root; }
void insert(Node *n);
void removeWithChildren(Node *n);
void remove(Node *n);
string prewalk(Node *n);
string inwalk(Node *n);
Node* search(Node *sub_tree,int key);
Node* minimum(Node *sub_tree);
Node* maximum(Node *sub_tree);
Node* getSuccessor(Node *n);
void forgetChild(Node *n);
void transplant(Node* u,Node*v);
};
析构函数调用 removeWithChildren(Node *n)
函数,参数是树的根。
我正在调用 remove(Node *n)
一次。当我不调用它时,没有错误。我逐步检查了代码,removeWithChildren
函数并未尝试删除被 remove
函数删除的节点。还是有错误。
编辑:我使用的是 Microsoft Visual Studio 2012 Express 版。 我不知道什么样的断点。
EDIT2:出于某种原因在 removeWithChildren
中注释掉 forgetChild
修复了错误。
最佳答案
您没有发布代码的相关部分,但您发布的内容让人猜测您既没有提供有效的复制构造函数,也没有阻止使用默认复制构造函数。然后你犯了按值传递对象的错误(当你应该按引用传递时)从而调用默认的复制构造函数和析构函数并破坏内存。
当使用复制构造困难且可能不必要的类时,请确保默认复制构造函数不可访问。
关于c++ - 为什么打印指针地址会触发断点?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31702898/