接着看删除部分,删除部分比插入要更难搞一些。对于删除,同样需要分情况讨论。
1.如果是在一个平衡节点下删除,只要把这个节点的高度信息修改就可以了
2.如果是在较长的子树下删除,就把这个节点的高度信息修改成平衡
以上两种情况都不需要进行旋转。
3.如果是在较短的子树下删除,除了更新高度信息外,还需要旋转节点。这时又分3种情况讨论。
3种情况的图如下,直接针对编程就可以了
与插入一样,删除时不必从树根开始更新,记录一个path_top即可。如果某个节点是平衡的,那么删除不会影响到它以上的节点,如果某个节点下的情况和图1相同,那么删除也不会影响到它以上的节点。这时可以把path_top设为该节点。另外,treep是指向删除节点右子树中最小的节点,如果用中序遍历,就是下个节点,将用它的值来代替删除节点。
int avl_delete(node *treep, value_t target)
{
/* delete the target from the tree, returning 1 on success or 0 if
* it wasn't found
*/
node tree = *treep, targetn;
node *path_top = treep;
node *targetp = NULL;
direction dir;
while (tree) {
dir = (target > tree->value);
if (target == tree->value)
targetp = treep;
if (tree->next[dir] == NULL)
break;
if (Balanced(tree)
|| (tree->longer == (1-dir) && Balanced(tree->next[1-dir]))
) path_top = treep;
treep = &tree->next[dir];
tree = *treep;
}
if (!targetp)
return 0;
/* adjust balance, but don't lose 'targetp' */
targetp = avl_rebalance_del(path_top, target, targetp);
/* We have re-balanced everything, it remains only to
* swap the end of the path (*treep == treep) with the deleted item
* (*targetp == targetn)
*/
avl_swap_del(targetp, treep, dir);
return 1;
}
这一段代码负责重新平衡树,除了最后一个node更新之外(tree-next[dir] == NULL),其余的都要更新高度信息,如有必要,还有旋转。
node *avl_rebalance_del(node *treep, value_t target, node *targetp)
{
/* each node from treep down towards target, but
* excluding the last, will have a subtree grow
* and need rebalancing
*/
node targetn = *targetp;
while (1) {
node tree = *treep;
direction dir = (target > tree->value);
if (tree->next[dir]==NULL)
break;
if (Balanced(tree))
tree->longer = 1-dir;
else if (tree->longer == dir)
tree->longer = NEITHER;
else {
// 对比图可以看到,这个是第三幅图的场景
if (tree->next[1-dir]->longer == dir)
avl_rotate_3_shrink(treep, dir);
else // 第一二幅图
avl_rotate_2_shrink(treep, dir);
// 这一句的作用,用targetp本身也在旋转过程中时,需要把它更新,targetp作为旋转的顶,而且三幅图里,都是转到&(*treep)->next[dir]
if (tree == targetn)
targetp = &(*treep)->next[dir];
}
// 为什么这里是tree而不是treep?
// 是treep也可以,但是旋转后treep是tree的,这样要多遍历一个节点
treep = &tree->next[dir];
}
return targetp;
}
交换并删除的代码比较简单,如下
void avl_swap_del(node *targetp, node *treep, direction dir)
{
node targetn = *targetp;
node tree = *treep;
*targetp = tree;
*treep = tree->next[1-dir];
tree->next[LEFT] = targetn->next[LEFT];
tree->next[RIGHT]= targetn->next[RIGHT];
tree->longer = targetn->longer;
free(targetn);
}
最后是后种旋转的代码实现,都比较直观,如果对着图看。
void avl_rotate_2_shrink(node *path_top, direction dir)
{
node D, B, C;
D = *path_top;
B = D->next[1-dir];
C = B->next[dir];
*path_top = B;
B->next[dir] = D;
D->next[1-dir] = C;
if (Balanced(B)) {
B->longer = dir;
D->longer = 1-dir;
} else {
B->longer = NEITHER;
D->longer = NEITHER;
}
}
void avl_rotate_3_shrink(node *path_top, direction dir)
{
node B, C, D, E, F;
F = *path_top;
B = F->next[1-dir];
D = B->next[dir];
C = D->next[1-dir];
E = D->next[dir];
*path_top = D;
D->next[1-dir] = B;
D->next[dir] = F;
B->next[dir] = C;
F->next[1-dir] = E;
B->longer = NEITHER;
F->longer = NEITHER;
if (D->longer == dir)
B->longer = 1-dir;
if (D->longer == 1-dir)
F->longer = dir;
D->longer = NEITHER;
}

- 大小: 6.5 KB

- 大小: 6.7 KB

- 大小: 9.1 KB
分享到:
相关推荐
在本项目中,我们将讨论如何结合这两种数据结构,利用avl树实现哈希表,以达到更好的性能效果。 首先,让我们了解一下avl树。avl树是一种自平衡二叉搜索树(BST),它的特点是任何节点的两个子树的高度最大差别不...
AVL树是一种自平衡二叉查找树(Self-Balancing Binary Search Tree),由G. M. Adelson-Velsky和E. M. Landis在1962年提出,因此得名AVL树,它是最早的自平衡二叉查找树之一。在AVL树中,任意节点的两个子树的高度差...
AVL树是一种自平衡的...总结来说,AVL树的C++实现是一个包含节点类、树类和相关操作实现的过程。通过理解和实现这个过程,你可以深入理解自平衡二叉搜索树的工作原理,并能够灵活地在自己的项目中应用这些数据结构。
AVL树的平衡性比红黑树更强,因此在查找效率上通常优于红黑树,但插入和删除操作可能需要更多的旋转,导致更复杂的实现。红黑树的平衡要求相对较宽松,插入和删除操作的代价较低,且在实践中表现良好,是许多语言...
在C语言中实现AVL树,首先需要定义AVL树的节点结构。每个节点包含三个部分:存储数据的关键字(key)、节点的高度(height)以及指向左子树和右子树的指针。一个简单的节点定义如下: ```c typedef struct AVLNode ...
学习AVL树的算法实现,使用c++在vc6.0中进行相应的算法实现,对正在学习算法的孩子有帮助
实验报告可能会详细解释这些操作的步骤,包括如何构建二叉查找树,如何实现AVL树的旋转算法,以及如何在实际应用中使用这些数据结构。此外,报告可能还会包含实验结果的分析,比如不同操作的运行时间比较,以及不...
在C++中实现AVL树,我们通常会使用模板类来实现泛型编程,这样可以使得AVL树能够处理不同类型的元素。以下是一个基本的AVL树节点定义: ```cpp template struct AVLNode { T data; int height; AVLNode* left; ...
7. **调试和测试**:在C#2005中,确保AVL树的实现正确性至关重要,可以通过插入一系列已知的数据,然后进行查找、插入和删除操作,检查结果是否符合预期。同时,调试过程中应关注旋转逻辑,确保每次操作后树依然保持...
`Form1.Designer.cs`、`Form1.resx`和`Form1.cs`可能涉及到用户界面的设计和逻辑,`RBTree.cs`和`AVLTree.cs`分别实现了红黑树和AVL树的类,而`TreeGraphics.cs`可能是用来绘制和展示树的图形部分,`MinAreaDraw.cs`...
在C++中实现AVL树,我们需要关注以下几个关键点: 1. **节点结构**:AVL树中的每个节点包含一个键值、指向左子树和右子树的指针,以及表示该节点平衡因子的整数值。平衡因子是节点的左子树高度减去右子树高度。典型...
在`avl_tree`这个文件中,很可能包含了AVL树的C++、Java或Python等编程语言的实现,包括节点定义、插入、删除和以括号表示法输出等功能。通过阅读和理解这些代码,你可以深入学习AVL树的工作原理和实际应用。
综上所述,"一个可以查找中位数的AVL树实现"涉及到的IT知识点包括AVL树的基本概念、平衡因子、旋转操作、节点计数处理、中位数查找算法以及在实际应用中的性能优化。理解并掌握这些知识点,将有助于开发高效的数据...
AVL树是一种自平衡二叉查找树(Binary Search Tree,BST),由Georgy Adelson-Velsky和Emanuel Land...相比于标准库中的红黑树实现,AVL树在保持平衡方面更严格,可能在某些操作上表现得更快,但实现和维护也更为复杂。
AVL树是一种自平衡二叉查找树(Binary Search Tree,...以上是C++实现AVL树的基础知识点,具体实现过程会涉及更多细节,如旋转的具体代码实现、错误处理等。在实际编码时,还需要注意C++语法和面向对象设计原则的运用。
6. Java编程:使用Java实现AVL树的优势在于,Java提供了强大的集合框架和图形用户界面库(如Swing或JavaFX),使得开发这样的项目变得相对容易。通过Java代码,我们可以清晰地看到数据结构和算法的实现,同时利用...
在"AVL树的细节实现_软件设计三班_郭威_1615925218"这个文件中,郭威同学可能详细阐述了AVL树的基本概念,详细描述了插入和删除操作的过程,并给出了相应的C++或Java代码实现。此外,他还可能进行了性能分析和对比...
本话题主要探讨了C++实现的二叉树、二叉搜索树以及AVL树,这些都是高级数据结构,对于优化算法和提高程序效率至关重要。 二叉树是一种特殊的树结构,每个节点最多只有两个子节点,通常分为左子节点和右子节点。在...
在计算机科学中,AVL树是最先发明的自平衡二叉查找树。在AVL树中任何节点的两个子树的高度最大差别为1,所以它也被称为高度平衡树。增加和删除可能需要通过一次或多次树旋转来重新平衡这个树。AVL树得名于它的发明者...