数据结构中的 AA 树2025年4月20日 | 阅读 13 分钟 AA 树简介由 **Arne Anderson** 发明的 **AA 树** 是一种自平衡二叉搜索树,旨在简化和加速实现。在二叉搜索树 (BST) 中,每个节点最多可以有两个子节点,并且父节点左侧的每个节点都小于父节点,右侧的每个节点都大于父节点。BST 的问题在于,它们会随着插入和删除的集合而**失衡**,导致搜索、插入和删除等操作的性能下降。通过旋转和保持简单结构,AA 树可以保持**高性能**。 基本属性AA 树通过几个关键概念与其他二叉搜索树区分开来。它们是:
方法一:递归方法在这种方法中,**插入、删除和遍历**等基本操作都是递归执行的。每个操作都会接受树,递归地遍历它,对节点进行分层,调整它们,并在满足 AA 树条件时实现倾斜和分裂。这是最简单的方法,尤其适用于小型到中型树。 程序输出 Inorder traversal of AA tree after insertion: 2 3 4 5 6 7 8 Inorder traversal of AA tree after deletion: 2 4 5 6 7 8 说明节点结构 (struct Node) 此结构模仿了 AA 树中的一个节点。 它包含三个主要属性:
构造函数使用提供的键初始化节点,并设置层级和子节点指针的默认值。 AATree 类 AA 树在此类中实现,并提供执行**插入、删除**和**遍历操作**的方法。 私有成员变量 root:树的根指针。 倾斜和分裂操作 **倾斜**和**分裂**,即私有成员,用于保持 AA 树的属性。skew 对给定节点执行倾斜操作,必要时调整树结构以保持层级顺序属性。split 对给定节点执行分裂操作,也重新排列树结构以维护层级顺序属性。 递归插入 (insertNode) 这个**私有成员函数**将一个带有指定键的新节点插入到**树中**。它利用递归来探索树并找到要插入的位置。然后,执行倾斜和分裂操作来重新平衡树。 递归方法 在这种方法中,**插入、删除和遍历**等基本操作都是递归执行的。每个操作都会接受树,递归地遍历它,对节点进行分层,调整它们,并在满足 AA 树条件时实现倾斜和分裂。这是最简单的方法,尤其适用于小型到中型树。 递归删除 (removeNode) 通过这个私有成员函数,可以从树中删除带有给定键的节点。它使用递归来查找要删除的节点,然后根据三种情况执行删除:节点没有子节点、节点只有一个父节点、链接具有其**后代**的子节点(由其后继替换),并在删除后通过执行倾斜和分裂操作来重新平衡树。 中序遍历 (inorderTraversal) 这个私有成员函数对树应用**中序遍历**。它递归地遍历左子树,然后访问当前节点,最后递归地遍历右子树。它遍历**节点**,并在打印**排序的**键的同时完成操作。 公共成员函数 insert:使用**insertNode**方法实现新键的插入。 remove:使用**removeNode**函数从树中删除一个权重。 traverseInorder:调用 `inorderTraversal` 函数来启动树的中序遍历。 主函数 在实例级别实例化 AATree 类。实际上,一些键将被从树中删除。输出是插入后的树的中序遍历。从树中删除一个键。显示删除后树的中序遍历。 复杂度分析时间复杂度 插入 在 AA 树中,插入的时间复杂度为**O(log n)**,其中 n 是树中的节点数。这种**层次结构**源于初始时将根分成两部分,然后向下直到将新元素插入到叶子中,以及倾斜和分裂操作以确保 AA 树的属性得到维护。 删除 类似地,AA 树中删除的时间复杂度为**O(log(n)**,其中 n 表示树中的节点数。与插入类似,删除步骤是通过移动到存在要删除节点的根节点,并且**删除**会留下内部倾斜和分裂操作来保留 AA 树的属性。 遍历 **中序遍历**的时间复杂度为**O(n)**,n 是树中的节点数。这是因为在遍历过程中,树中的每个节点都必须只访问一次。 空间复杂度 所提供 AA 树的**空间复杂度**为**O(n)**,其中 n 是树中的节点数。这部分空间主要用于在内存中存储树节点。此外,插入和删除操作可能会导致递归函数调用,这会在调用堆栈上占用额外的内存。但是,总的空间复杂度仍然是**O(n)**。 方法二:迭代方法这种方法避免了复制,并通过使用循环或**堆栈**或**队列**数据结构来**迭代**地执行基本操作。例如,在循环中,它需要调整节点。与递归方法相比,递归方法可能更复杂,但对于非常深的树可能更有效,因为递归调用的减少带来了开销的降低。 程序输出 After insertion: Inorder traversal of AA tree: 2 10 15 3 4 6 After deletion: Inorder traversal of AA tree: 1 0 10 15 3 4 6 说明AATree 类 它包括迭代插入(insert)、迭代删除(remove)、迭代**中序遍历**(traverseInorder)以及打印树的显示结构的过程。root 成员变量用于保存树的根节点的位置。 倾斜操作 skew 函数用于执行倾斜操作以保持 AA 树的属性。它以一个节点作为输入,并在需要倾斜转换时执行。 分裂操作 负责分裂的方法确保了**AA 树**的特性。它需要一个节点(供进一步处理)。否则,它执行分裂转换。 迭代插入 AA 树通过 insert 方法扩展其新键。它使用递归树遍历、一个堆栈将相关节点压入堆栈,最后将节点插入到适当的位置。更新后,通过以**迭代方式**应用倾斜和分裂操作来重新平衡树。 迭代删除 remove 方法涉及从 AA 树中提取键。它使用堆栈递归地查找该键节点。它使用堆栈递归地查找该键节点。在此过程中,根据情况(无子节点、一个子节点或两个子节点),它会删除节点并使用倾斜和分裂操作以迭代方式重新平衡树。 迭代方法 该方法避免了**复制**,并通过使用循环或堆栈或队列数据结构来**迭代**地执行基本操作。例如,在循环中,它需要调整节点。与递归方法相比,递归方法可能更复杂,但对于非常深的树可能更有效,因为**递归调用的减少**带来了开销的降低。 迭代中序遍历 **traverseInorder** 方法在不使用递归函数的情况下执行树的中序遍历。它使用堆栈来记录遍历的节点,并按遍历的升序打印键。 结果 print 方法提供 AA 树的中序遍历,从而按排序顺序打印键。 主函数 在 main 函数中,代码创建了 **AATree 类的实例并将键插入到类中。它显示了**插入**发生时重新排列的树结构。接下来,它查找要从树中删除的键,然后显示删除后树的结构。 复杂度分析时间复杂度 插入 **迭代插入**意味着插入以类似的方式进行,树被迭代遍历。作为**O(log n)**的平均复杂度,遍历过程所需的时间与树中的节点数 n 成正比。需要注意的另一件事是,使用倾斜和分裂操作重新平衡树都需要**O(log n**)时间。因此,插入的总时间复杂度等于**O(log n)**。 删除 就像插入一样,迭代删除的特点是迭代搜索要删除的节点,这需要平均 log n 的时间。删除节点并使用倾斜和分裂操作重新平衡树也需要**O(log n)**。因此,删除复杂度为**O(log n)**。 遍历 **迭代中序**遍历方法遍历树中的每个节点,每个节点只访问一次。因此,遍历操作的复杂度为**O(n)**,其中 n 是树中的节点数。 空间复杂度 该实现的**空间复杂度**主要包括用于迭代遍历和重新平衡操作的堆栈的空间。由于它用作节点指针,因此堆栈内存的最大大小与树的高度成正比。对于 AA 树,在最坏情况下,高度为**O(log n)**,其中 n 是节点总数。因此,该算法的实现具有**O(log n)**的空间复杂度。 下一个主题图数据结构 |
我们请求您订阅我们的新闻通讯以获取最新更新。