gpt4 book ai didi

c++ - 通用二叉树节点析构函数问题

转载 作者:搜寻专家 更新时间:2023-10-31 00:01:35 25 4
gpt4 key购买 nike

我一直在做一项作业,现在我被有问题的析构函数困住了。我必须创建一个具有所有常用成员函数和一些特殊运算符的通用二叉树。还有一个限制:一切都必须迭代工作,所以这次没有讨厌的递归黑客。

BinTreeNode 类的析构函数显然有问题,因为如果我像这样删除节点:

BinTreeNode<int> * node = new BinTreeNode<int>();
delete node;

我仍然可以访问它的数据:

node->getData(); //should fail miserably

所以删除没有效果,但我不知道应该如何更正析构函数。在我看来,该算法应该是正确的,所以我怀疑我使用指针的方式有问题,但在这一点上我很困惑,我什至不理解我自己的代码。

到目前为止我的代码:

二叉树.h

#ifndef BINTREE_H_
#define BINTREE_H_

#ifndef NULL
#define NULL 0
#endif

#include "BinTreeNode.h"

template <class T>
class BinTree
{
private:
BinTreeNode<T> * root;
public:
//constructors and destructor
BinTree():
root(NULL){}

BinTree(T data):
root(new BinTreeNode<T>(data)){}

~BinTree();

//search
BinTreeNode<T> * search(T data);

//insert
bool insert(T data);

//remove
bool remove(T data);
};

template <class T>
BinTree<T>::~BinTree()
{
delete root;
}

template <class T>
BinTreeNode<T> * BinTree<T>::search(T data)
{
BinTreeNode<T> * node = new BinTreeNode<T>(data);
BinTreeNode<T> * current = root;

while (current != NULL)
{
if (*current == *node)
{
delete node;
return root;
}
else if (*node < *current)
{
current = current->getLeft();
}
else
{
current = current->getRight();
}
}
delete node;
return NULL;
}

template <class T>
bool BinTree<T>::insert(T data)
{
BinTreeNode<T> * node = new BinTreeNode<T>(data);
BinTreeNode<T> * current = root;

while (current != NULL)
{
if (*current == *node)
{
delete node;
return false;
}
else if (*node < *current)
{
if (current->getLeft() == NULL)
{
current->setLeft(node);
return true;
}
else
{
current = current->getLeft();
}
}
else
{
if (current->getRight() == NULL)
{
current->setRight(node);
return true;
}
else
{
current = current->getRight();
}
}
}
return false;
}

#endif

BinTreeNode.h

#ifndef BINTREENODE_H_
#define BINTREENODE_H_

#ifndef NULL
#define NULL 0
#endif

template <class T>
class BinTreeNode
{
private:
T data;
BinTreeNode<T> *left, *right, *parent;
public:
//constructors and destructor
BinTreeNode():
data(NULL), left(NULL), right(NULL), parent(NULL){}

BinTreeNode(T data):
data(data), left(NULL), right(NULL), parent(NULL){}

~BinTreeNode();

//set and get data member
T getData() const;

void setData(T data);

//set and get left and right branches
BinTreeNode<T> * getLeft() const;

BinTreeNode<T> * getRight() const;

void setLeft(BinTreeNode<T> * node);

void setRight(BinTreeNode<T> * node);

//set and get parent
BinTreeNode<T> * getParent() const;

void setParent(BinTreeNode<T> * node);

//comparison operators
bool operator<(const BinTreeNode<T>& node) const;
bool operator>(const BinTreeNode<T>& node) const;
bool operator==(const BinTreeNode<T>& node) const;
};

template <class T>
BinTreeNode<T>::~BinTreeNode()
{
BinTreeNode<T> * current = this;
BinTreeNode<T> * parent = NULL;
while (current != NULL)
{
parent = current->getParent();
if (current->getLeft() == NULL)
current = current->getLeft();
else if (current->getRight() == NULL)
current = current->getRight();
else
{
if (parent->getRight() == current)
parent->setRight(NULL);
else
parent->setLeft(NULL);
current = NULL; // this line (among others) is very suspicious
}
current = parent;
}
}

template <class T>
T BinTreeNode<T>::getData() const
{
return data;
}

template <class T>
void BinTreeNode<T>::setData(T data)
{
this->data = data;
}

template <class T>
BinTreeNode<T> * BinTreeNode<T>::getLeft() const
{
return left;
}

template <class T>
BinTreeNode<T> * BinTreeNode<T>::getRight() const
{
return right;
}

template <class T>
void BinTreeNode<T>::setLeft(BinTreeNode<T> * node)
{
node->setParent(this);
left = node;
}

template <class T>
void BinTreeNode<T>::setRight(BinTreeNode<T> * node)
{
node->setParent(this);
right = node;
}

template <class T>
BinTreeNode<T> * BinTreeNode<T>::getParent() const
{
return parent;
}

template <class T>
void BinTreeNode<T>::setParent(BinTreeNode<T> * node)
{
parent = node;
}

template <class T>
bool BinTreeNode<T>::operator<(const BinTreeNode<T>& node) const
{
return this->data < node.data;
}

template <class T>
bool BinTreeNode<T>::operator>(const BinTreeNode<T>& node) const
{
return this->data > node.data;
}

template <class T>
bool BinTreeNode<T>::operator==(const BinTreeNode<T>& node) const
{
return this->data == node.data;
}

#endif /* BINTREENODE_H_ */

最佳答案

您的 BinTreeNode 析构函数应该只是:

template <class T>
BinTreeNode<T>::~BinTreeNode() {
delete left;
delete right;
}

这将递归调用 left 和 right 的析构函数,释放为这些节点及其子节点分配的内存。这将因此释放整棵树。

NULL 分配给指针不会释放它指向的内存。

另一方面,你提到的,删除后,这一行:

node->getData();

仍然返回数据,完全正常。删除会释放内存,但存储在其中的数据可能仍然可用一段时间,直到在该内存地址中写入新内容。访问已经释放的内存地址意味着未定义的行为。

顺便说一句,您应该在 C++ 中使用“0”(不带引号)而不是 NULL。因此,没有必要使用 #ifndef NULL(...)。

编辑:我没有看到“无递归”评论。这是一个非递归算法:

#include <deque>

/* ... */

template <class T>
BinTreeNode<T>::~BinTreeNode() {
std::deque deq;
// we're going to delete our children
deq.push_back(this);
while(deq.size()) {
BinTreeNode<T> *ptr = deq.front();
deq.pop_front();
if(ptr) {
deq.push_back(ptr->left);
deq.push_back(ptr->right);
// we don't want the child nodes
// to double delete the children
ptr->left = 0;
ptr->right = 0;
// avoid deleteing ourselves
if(ptr != this)
delete ptr;
}
}
}

我还没有测试过,但应该可以。

关于c++ - 通用二叉树节点析构函数问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9745736/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com