我正在实施一个AVL搜索树。到目前为止,我已经完成了编码部分,并且已经开始测试它的错误。我发现我的节点旋转方法被窃听,为了上帝的缘故,我不明白是什么问题。二叉树旋转
该算法的工作原理应该是在纸上,但是当在机器上执行时,它会泄漏树节点。
这是用于节点向左旋转的方法:http://pastebin.com/mPHj29Af
bool avl_search_tree::avl_tree_node::rotate_left()
{
if (_right_child != NULL) {
avl_tree_node *new_root = _right_child;
if (_parent != NULL) {
if (_parent->_left_child == this) {
_parent->_left_child = new_root;
} else {
_parent->_right_child = new_root;
}
}
new_root->_parent = _parent;
_parent = new_root;
_right_child = new_root->_left_child;
new_root->_left_child = this;
if (_right_child != NULL) {
_right_child->_parent = this;
}
//update heights
update_height();
new_root->update_height();
return true;
}
return false;
}
在我的插入方法我评论的AVL平衡的一部分,而是我只是想旋转新插入的节点到剩下。以升序插入整数的结果:我的树只包含初始根(插入的第一个节点),并且所有其他节点都泄露。
任何帮助确定问题是高度赞赏,因为我开始发疯。
为了记录:如果我没有使用任何旋转,树不会泄漏节点,它可以用作正常的不平衡二叉搜索树(用于插入和查找)。
编辑:由于AJG85的评论我要补充意见:
我加的printf“支票”来的avl_search_tree :: avl_tree_node析构函数方法将打印键值(在我的情况下32位整数)在清理之前,以及将打印刚刚插入的密钥的avl_search_tree的插入方法。
然后在程序的入口点上,我在堆上分配一个avl_search_tree,并按照升序添加键,然后删除它。
随着AVL平衡使我得到在终端输出如下:
bool avl_search_tree::insert(const int&) : 1
bool avl_search_tree::insert(const int&) : 2
bool avl_search_tree::insert(const int&) : 3
bool avl_search_tree::insert(const int&) : 4
bool avl_search_tree::insert(const int&) : 5
bool avl_search_tree::insert(const int&) : 6
bool avl_search_tree::insert(const int&) : 7
bool avl_search_tree::insert(const int&) : 8
avl_search_tree::avl_tree_node::~avl_tree_node() : 1
这意味着thatall插入成功,但只有根已被删除。
AVL Balancing将其注释掉,它就像普通的二叉搜索树一样工作。终端输出是:
bool avl_search_tree::insert(const int&) : 1
bool avl_search_tree::insert(const int&) : 2
bool avl_search_tree::insert(const int&) : 3
bool avl_search_tree::insert(const int&) : 4
bool avl_search_tree::insert(const int&) : 5
bool avl_search_tree::insert(const int&) : 6
bool avl_search_tree::insert(const int&) : 7
bool avl_search_tree::insert(const int&) : 8
avl_search_tree::avl_tree_node::~avl_tree_node() : 1
avl_search_tree::avl_tree_node::~avl_tree_node() : 2
avl_search_tree::avl_tree_node::~avl_tree_node() : 3
avl_search_tree::avl_tree_node::~avl_tree_node() : 4
avl_search_tree::avl_tree_node::~avl_tree_node() : 5
avl_search_tree::avl_tree_node::~avl_tree_node() : 6
avl_search_tree::avl_tree_node::~avl_tree_node() : 7
avl_search_tree::avl_tree_node::~avl_tree_node() : 8
这意味着一切都已妥善清理。
现在......我是如何得出旋转方法是问题的结论?在注释的AVL平衡子程序下,我添加了一条线,将每个新插入的节点旋转到左侧。结果?与AVL Balancing子例程启用相同。
关于update_height()方法,它不会以任何方式改变树的结构。
我希望这会澄清它。
编辑2:
要澄清一些更多的东西,他是avl_tree_node析构函数是如何实现的:
avl_search_tree::avl_tree_node::~avl_tree_node()
{
printf("%s : %d\n", __PRETTY_FUNCTION__, *_key);
if (_left_child != NULL) {
delete _left_child;
}
if (_right_child != NULL) {
delete _right_child;
}
if (_key != NULL) {
delete _key;
}
}
_left_child和_right_child是指向avl_tree_node在堆中分配的对象。
编辑3:
由于AGJ85的第二个意见,我发现这个问题。在我的旋转方法中,我忘记了实际上每当根被移位时我都必须更新树的根指针。
基本上树的根始终指向第一个插入的节点,并且在需要时不更新指针,我的旋转方法会泄漏实际配置正确的新树的根。 :)
谢谢AGJ85!
习惯上粘贴相关的代码,特别是因为它相当短。 – Xion
没有足够的代码/信息来识别问题。成员的其他用法和方法的定义是未知的。理想情况下,您将调试并描述您观察到的内容和/或提供描述可编译问题的示例代码。 – AJG85
实现一个AVL树是一个通过仪式,havefun :) 关于主题,虽然:1)你是什么意思的“不起作用”和2)如果你只是自己调用它们或者是仅在插入时出现问题? – hugomg