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

 更新时间:2020年12月21日 15:40:20   作者:_慕  
这篇文章主要介绍了Python 实现二叉查找树的示例代码,帮助大家更好的理解和使用python,感兴趣的朋友可以了解下

二叉查找树

  • 所有 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使用paramiko执行服务器脚本并拿到实时结果

    python使用paramiko执行服务器脚本并拿到实时结果

    这篇文章主要介绍了python使用paramiko执行服务器脚本并拿到实时结果,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-12-12
  • Python 字典一个键对应多个值的方法

    Python 字典一个键对应多个值的方法

    这篇文章主要介绍了Python 字典一个键对应多个值的方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-09-09
  • python根据出生日期返回年龄的方法

    python根据出生日期返回年龄的方法

    这篇文章主要介绍了python根据出生日期返回年龄的方法,实例分析了Python时间操作的技巧,非常具有实用价值,需要的朋友可以参考下
    2015-03-03
  • 用Python监控NASA TV直播画面的实现步骤

    用Python监控NASA TV直播画面的实现步骤

    本文分享一个名为"Spacestills"的开源程序,它可以用于查看 NASA TV 的直播画面(静止帧)
    2021-05-05
  • 对pandas里的loc并列条件索引的实例讲解

    对pandas里的loc并列条件索引的实例讲解

    今天小编就为大家分享一篇对pandas里的loc并列条件索引的实例讲解,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2018-11-11
  • 使用 Python 和 Selenium 解决 Cloudflare 验证码的问题

    使用 Python 和 Selenium 解决 Cloudflare&

    Cloudflare 验证码是一种用于区分人类用户和自动化机器人的功能,它是 Cloudflare 安全服务的重要组成部分,旨在防御网站免受自动化攻击和滥用,这篇文章主要介绍了使用 Python 和 Selenium 解决 Cloudflare 验证码,需要的朋友可以参考下
    2024-06-06
  • Python实现简单的用户交互方法详解

    Python实现简单的用户交互方法详解

    这篇文章给大家分享了关于Python实现简单的用户交互的相关知识点内容,有需要的朋友们可以学习下。
    2018-09-09
  • 轻松实现python搭建微信公众平台

    轻松实现python搭建微信公众平台

    这篇文章主要介绍了python搭建微信公众平台的相关资料和技巧,文中给出了详细的python搭建微信公众平台的步骤,感兴趣的朋友可以参考一下
    2016-02-02
  • Python Requests库及用法详解

    Python Requests库及用法详解

    Requests库作为Python中最受欢迎的HTTP库之一,为开发人员提供了简单而强大的方式来发送HTTP请求和处理响应,本文将带领您深入探索Python Requests库的世界,我们将从基础知识开始,逐步深入,覆盖各种高级用法和技巧,感兴趣的朋友一起看看吧
    2024-06-06
  • pyspark操作hive分区表及.gz.parquet和part-00000文件压缩问题

    pyspark操作hive分区表及.gz.parquet和part-00000文件压缩问题

    这篇文章主要介绍了pyspark操作hive分区表及.gz.parquet和part-00000文件压缩问题,针对问题整理了spark操作hive表的几种方式,需要的朋友可以参考下
    2021-08-08

最新评论