Python 实现二叉查找树的示例代码


Posted in Python onDecember 21, 2020

二叉查找树

  • 所有 key 小于 V 的都被存储在 V 的左子树
  • 所有 key 大于 V 的都存储在 V 的右子树

BST 的节点

class BSTNode(object):
  def __init__(self, key, value, left=None, right=None):
    self.key, self.value, self.left, self.right = key, value, left, right

二叉树查找

如何查找一个指定的节点呢,根据定义我们知道每个内部节点左子树的 key 都比它小,右子树的 key 都比它大,所以 对于带查找的节点 search_key,从根节点开始,如果 search_key 大于当前 key,就去右子树查找,否则去左子树查找

NODE_LIST = [
  {'key': 60, 'left': 12, 'right': 90, 'is_root': True},
  {'key': 12, 'left': 4, 'right': 41, 'is_root': False},
  {'key': 4, 'left': 1, 'right': None, 'is_root': False},
  {'key': 1, 'left': None, 'right': None, 'is_root': False},
  {'key': 41, 'left': 29, 'right': None, 'is_root': False},
  {'key': 29, 'left': 23, 'right': 37, 'is_root': False},
  {'key': 23, 'left': None, 'right': None, 'is_root': False},
  {'key': 37, 'left': None, 'right': None, 'is_root': False},
  {'key': 90, 'left': 71, 'right': 100, 'is_root': False},
  {'key': 71, 'left': None, 'right': 84, 'is_root': False},
  {'key': 100, 'left': None, 'right': None, 'is_root': False},
  {'key': 84, 'left': None, 'right': None, 'is_root': False},
]


class BSTNode(object):
  def __init__(self, key, value, left=None, right=None):
    self.key, self.value, self.left, self.right = key, value, left, right


class BST(object):
  def __init__(self, root=None):
    self.root = root

  @classmethod
  def build_from(cls, node_list):
    cls.size = 0
    key_to_node_dict = {}
    for node_dict in node_list:
      key = node_dict['key']
      key_to_node_dict[key] = BSTNode(key, value=key)  # 这里值和key一样的

    for node_dict in node_list:
      key = node_dict['key']
      node = key_to_node_dict[key]
      if node_dict['is_root']:
        root = node
      node.left = key_to_node_dict.get(node_dict['left'])
      node.right = key_to_node_dict.get(node_dict['right'])
      cls.size += 1
    return cls(root)

  def _bst_search(self, subtree, key):
    """
    subtree.key小于key则去右子树找 因为 左子树<subtree.key<右子树
    subtree.key大于key则去左子树找 因为 左子树<subtree.key<右子树
    :param subtree:
    :param key:
    :return:
    """
    if subtree is None:
      return None
    elif subtree.key < key:
      self._bst_search(subtree.right, key)
    elif subtree.key > key:
      self._bst_search(subtree.left, key)
    else:
      return subtree

  def get(self, key, default=None):
    """
    查找树
    :param key:
    :param default:
    :return:
    """
    node = self._bst_search(self.root, key)
    if node is None:
      return default
    else:
      return node.value

  def _bst_min_node(self, subtree):
    """
    查找最小值的树
    :param subtree:
    :return:
    """
    if subtree is None:
      return None
    elif subtree.left is None:
      # 找到左子树的头
      return subtree
    else:
      return self._bst_min_node(subtree.left)

  def bst_min(self):
    """
    获取最小树的value
    :return:
    """
    node = self._bst_min_node(self.root)
    if node is None:
      return None
    else:
      return node.value

  def _bst_max_node(self, subtree):
    """
    查找最大值的树
    :param subtree:
    :return:
    """
    if subtree is None:
      return None
    elif subtree.right is None:
      # 找到右子树的头
      return subtree
    else:
      return self._bst_min_node(subtree.right)

  def bst_max(self):
    """
    获取最大树的value
    :return:
    """
    node = self._bst_max_node(self.root)
    if node is None:
      return None
    else:
      return node.value

  def _bst_insert(self, subtree, key, value):
    """
    二叉查找树插入
    :param subtree:
    :param key:
    :param value:
    :return:
    """
    # 插入的节点一定是根节点,包括 root 为空的情况
    if subtree is None:
      subtree = BSTNode(key, value)
    elif subtree.key > key:
      subtree.left = self._bst_insert(subtree.left, key, value)
    elif subtree.key < key:
      subtree.right = self._bst_insert(subtree.right, key, value)
    return subtree

  def add(self, key, value):
    # 先去查一下看节点是否已存在
    node = self._bst_search(self.root, key)
    if node is not None:
      # 更新已经存在的 key
      node.value = value
      return False
    else:
      self.root = self._bst_insert(self.root, key, value)
      self.size += 1

  def _bst_remove(self, subtree, key):
    """
    删除并返回根节点
    :param subtree:
    :param key:
    :return:
    """
    if subtree is None:
      return None
    elif subtree.key > key:
      subtree.right = self._bst_remove(subtree.right, key)
      return subtree
    elif subtree.key < key:
      subtree.left = self._bst_remove(subtree.left, key)
      return subtree
    else:
      # 找到了需要删除的节点
      # 要删除的节点是叶节点 返回 None 把其父亲指向它的指针置为 None
      if subtree.left is None and subtree.right is None:
        return None
      # 要删除的节点有一个孩子
      elif subtree.left is None or subtree.right is None:
        # 返回它的孩子并让它的父亲指过去
        if subtree.left is not None:
          return subtree.left
        else:
          return subtree.right
      else:
        # 有两个孩子,寻找后继节点替换,并从待删节点的右子树中删除后继节点
        # 后继节点是待删除节点的右孩子之后的最小节点
        # 中(根)序得到的是一个排列好的列表 后继节点在待删除节点的后边
        successor_node = self._bst_min_node(subtree.right)
        # 用后继节点替换待删除节点即可保持二叉查找树的特性 左<根<右
        subtree.key, subtree.value = successor_node.key, successor_node.value
        # 从待删除节点的右子树中删除后继节点,并更新其删除后继节点后的右子树
        subtree.right = self._bst_remove(subtree.right, successor_node.key)
        return subtree

  def remove(self, key):
    assert key in self
    self.size -= 1
    return self._bst_remove(self.root, key)

以上就是Python 实现二叉查找树的示例代码的详细内容,更多关于Python 实现二叉查找树的资料请关注三水点靠木其它相关文章!

Python 相关文章推荐
python+mysql实现简单的web程序
Sep 11 Python
python使用xlrd模块读写Excel文件的方法
May 06 Python
python读写json文件的简单实现
Apr 11 Python
Flask框架Flask-Principal基本用法实例分析
Jul 23 Python
Python的argparse库使用详解
Oct 09 Python
Python中new方法的详解
Jan 15 Python
详解Python3中ceil()函数用法
Feb 19 Python
Django 对IP访问频率进行限制的例子
Aug 30 Python
用python解压分析jar包实例
Jan 16 Python
Python编程快速上手——疯狂填词程序实现方法分析
Feb 29 Python
python图片剪裁代码(图片按四个点坐标剪裁)
Mar 10 Python
Python如何在bool函数中取值
Sep 21 Python
如何利用Python matplotlib绘制雷达图
Dec 21 #Python
OpenCV+python实现膨胀和腐蚀的示例
Dec 21 #Python
python opencv肤色检测的实现示例
Dec 21 #Python
OpenCV+Python3.5 简易手势识别的实现
Dec 21 #Python
如何使用python-opencv批量生成带噪点噪线的数字验证码
Dec 21 #Python
python 录制系统声音的示例
Dec 21 #Python
用python发送微信消息
Dec 21 #Python
You might like
Discuz 模板语句分析及知识技巧
2009/08/21 PHP
php各种编码集详解和以及在什么情况下进行使用
2011/09/11 PHP
浅析PHP绘图技术
2013/07/03 PHP
php延迟静态绑定实例分析
2015/02/08 PHP
浅谈本地WAMP环境的搭建
2015/05/13 PHP
PHP Header失效的原因分析及解决方法
2016/11/16 PHP
Yii2框架自定义验证规则操作示例
2019/02/08 PHP
Javascript中的数学函数
2007/04/04 Javascript
可实现多表单提交的javascript函数
2007/08/01 Javascript
Javascript中的var_dump函数实现代码
2009/09/07 Javascript
mvc中form表单提交的三种方式(推荐)
2016/08/10 Javascript
vuex实现简易计数器
2016/10/27 Javascript
Bootstrap导航简单实现代码
2017/03/06 Javascript
详解http访问解析流程原理
2017/10/18 Javascript
JS计算距当前时间的时间差实例
2017/12/29 Javascript
vue-quill-editor富文本编辑器简单使用方法
2018/09/21 Javascript
微信小程序之数据绑定原理解析
2019/08/14 Javascript
jquery添加div实现消息聊天框
2020/02/08 jQuery
JS+HTML实现自定义上传图片按钮并显示图片功能的方法分析
2020/02/12 Javascript
vue 在methods中调用mounted的实现操作
2020/08/07 Javascript
Python 编码Basic Auth使用方法简单实例
2017/05/25 Python
Python编程之string相关操作实例详解
2017/07/22 Python
Sublime开发python程序的示例代码
2018/01/24 Python
python线程池threadpool实现篇
2018/04/27 Python
python中virtualenvwrapper安装与使用
2018/05/20 Python
在mac下查找python包存放路径site-packages的实现方法
2018/11/06 Python
Python 3.6打包成EXE可执行程序的实现
2019/10/18 Python
将python安装信息加入注册表的示例
2019/11/20 Python
python怎么调用自己的函数
2020/07/01 Python
Python调用C/C++的方法解析
2020/08/05 Python
Python中return函数返回值实例用法
2020/11/19 Python
python中常用的数据结构介绍
2021/01/12 Python
HTML5 实现图片上传预处理功能
2020/02/06 HTML / CSS
招标承诺书
2014/08/30 职场文书
2015年小学生自我评价范文
2015/03/03 职场文书
IDEA中sout快捷键无效问题的解决方法
2022/07/23 Java/Android