当前位置: 首页 > news >正文

06_自平衡二叉搜索树

菜鸟:老鸟,我最近在项目中遇到一个问题。我们需要频繁地插入、删除和查找数据,但我发现数据结构的操作速度变得很慢。你有什么建议吗?

老鸟:这个问题很常见。你目前用的是什么数据结构?

菜鸟:我用的是普通的二叉搜索树(BST)。

老鸟:普通的BST在最坏情况下会退化成链表,导致操作时间复杂度变成O(n)。你可以试试自平衡二叉搜索树(AVL树或红黑树),它们能保持树的高度在O(log n),从而提高性能。

渐进式介绍概念

菜鸟:自平衡二叉搜索树?听起来很复杂,能详细说说吗?

老鸟:当然。自平衡二叉搜索树是一种特殊的二叉搜索树,它通过在插入和删除节点时进行旋转操作来保持树的平衡,以确保树的高度始终在O(log n)。今天我们以AVL树为例来讲解。

菜鸟:AVL树是怎么保持平衡的?

老鸟:AVL树在每个节点上保存一个平衡因子(左右子树的高度差),并在需要时进行旋转操作来保持平衡。

代码示例与分析

插入操作

老鸟:让我们从插入操作开始,先看一段代码:

class Node:def __init__(self, key):self.key = keyself.left = Noneself.right = Noneself.height = 1class AVLTree:def insert(self, root, key):if not root:return Node(key)elif key < root.key:root.left = self.insert(root.left, key)else:root.right = self.insert(root.right, key)root.height = 1 + max(self.get_height(root.left), self.get_height(root.right))balance = self.get_balance(root)# Left Left Caseif balance > 1 and key < root.left.key:return self.right_rotate(root)# Right Right Caseif balance < -1 and key > root.right.key:return self.left_rotate(root)# Left Right Caseif balance > 1 and key > root.left.key:root.left = self.left_rotate(root.left)return self.right_rotate(root)# Right Left Caseif balance < -1 and key < root.right.key:root.right = self.right_rotate(root.right)return self.left_rotate(root)return rootdef left_rotate(self, z):y = z.rightT2 = y.lefty.left = zz.right = T2z.height = 1 + max(self.get_height(z.left), self.get_height(z.right))y.height = 1 + max(self.get_height(y.left), self.get_height(y.right))return ydef right_rotate(self, z):y = z.leftT3 = y.righty.right = zz.left = T3z.height = 1 + max(self.get_height(z.left), self.get_height(z.right))y.height = 1 + max(self.get_height(y.left), self.get_height(y.right))return ydef get_height(self, root):if not root:return 0return root.heightdef get_balance(self, root):if not root:return 0return self.get_height(root.left) - self.get_height(root.right)

菜鸟:看起来有点复杂,能解释一下吗?

老鸟:好的。首先,我们定义了一个节点类Node,它包含键值、高度和左右子节点。然后我们定义了AVLTree类,包含插入操作、左右旋转操作和获取高度及平衡因子的方法。

旋转操作

菜鸟:旋转操作是干什么用的?

老鸟:旋转操作用于调整树的结构以保持平衡。左旋转和右旋转是基本的旋转操作:

  • 左旋转:用于处理右重的情况。
  • 右旋转:用于处理左重的情况。

问题与优化

菜鸟:插入操作已经很清楚了,那删除操作呢?

老鸟:删除操作与插入操作类似,也需要调整平衡。具体代码如下:

def delete(self, root, key):if not root:return rootelif key < root.key:root.left = self.delete(root.left, key)elif key > root.key:root.right = self.delete(root.right, key)else:if root.left is None:temp = root.rightroot = Nonereturn tempelif root.right is None:temp = root.leftroot = Nonereturn temptemp = self.get_min_value_node(root.right)root.key = temp.keyroot.right = self.delete(root.right, temp.key)if root is None:return rootroot.height = 1 + max(self.get_height(root.left), self.get_height(root.right))balance = self.get_balance(root)if balance > 1 and self.get_balance(root.left) >= 0:return self.right_rotate(root)if balance > 1 and self.get_balance(root.left) < 0:root.left = self.left_rotate(root.left)return self.right_rotate(root)if balance < -1 and self.get_balance(root.right) <= 0:return self.left_rotate(root)if balance < -1 and self.get_balance(root.right) > 0:root.right = self.right_rotate(root.right)return self.left_rotate(root)return rootdef get_min_value_node(self, root):if root is None or root.left is None:return rootreturn self.get_min_value_node(root.left)

菜鸟:明白了,删除操作也需要旋转来保持平衡。

适用场景与误区

菜鸟:那自平衡二叉搜索树适用于哪些场景呢?

老鸟:自平衡二叉搜索树非常适合需要频繁插入、删除和查找操作的场景,如数据库索引和内存中的数据结构。

菜鸟:那有什么常见的误区需要注意吗?

老鸟:一个常见的误区是忽略了旋转操作的复杂度。虽然旋转操作在常数时间内完成,但在频繁插入和删除时,旋转操作会显著影响性能。

总结与延伸阅读

老鸟:总结一下,自平衡二叉搜索树通过插入和删除时的旋转操作保持树的平衡,从而确保操作的时间复杂度为O(log n)。你可以进一步了解红黑树,它是另一种常见的自平衡二叉搜索树。

菜鸟:非常感谢,老鸟!我会继续研究这些概念。

老鸟:不客气。你可以参考《算法导论》和《数据结构与算法分析》这两本书来深入学习这些数据结构。


http://www.mrgr.cn/news/24033.html

相关文章:

  • 【Petri网导论学习笔记】Petri网导论入门学习(二)
  • java基础-IO(6)转换流InputStreamReader、OutputStreamWriter
  • 元学习之应用案例
  • UML之类图详解
  • 《深入理解 JavaScript 中的定时器》
  • 一篇文章搞懂SQL优化
  • 学会这2项技能,普通人每年多赚10万+,互联网创业者必备!
  • Kerberos:更安全的网络认证协议
  • 香帅的金融学讲义:深入剖析与解读
  • Sklearn的datasets模块与自带数据集介绍
  • 使用 gdb 在汇编指令层面对程序注入、修改
  • 数据结构与算法1: 链表
  • Linux内核 -- 内存管理之 lru_cache_add_inactive_or_unevictable 函数
  • [Linux]:文件(下)
  • MySQL-CRUD入门2
  • 网络初识-相关概念
  • 《深度学习》OpenCV 高阶 图像直方图、掩码图像 参数解析及案例实现
  • 神经处理单元(NPU)小知识
  • 通信电路和信道的区别与联系
  • 004——双向链表和循环链表