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实现带错误处理功能的远程文件读取方法
Apr 29 Python
Python使用email模块对邮件进行编码和解码的实例教程
Jul 01 Python
python 排序算法总结及实例详解
Sep 28 Python
Python实现对象转换为xml的方法示例
Jun 08 Python
Python实现删除列表中满足一定条件的元素示例
Jun 12 Python
解决Tensorflow安装成功,但在导入时报错的问题
Jun 13 Python
python SocketServer源码深入解读
Sep 17 Python
Pytorch 之修改Tensor部分值方式
Dec 27 Python
TFRecord格式存储数据与队列读取实例
Jan 21 Python
浅谈对python中if、elif、else的误解
Aug 20 Python
python实现图片转字符画的完整代码
Feb 21 Python
Python基础之hashlib模块详解
May 06 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
PHP mkdir()无写权限的问题解决方法
2014/06/19 PHP
CodeIgniter实现从网站抓取图片并自动下载到文件夹里的方法
2015/06/17 PHP
ThinkPHP3.2.1图片验证码实现方法
2016/08/19 PHP
thinkPHP5使用Rabc实现权限管理
2019/08/28 PHP
PHP设计模式(七)组合模式Composite实例详解【结构型】
2020/05/02 PHP
javascript权威指南 学习笔记之null和undefined
2011/09/25 Javascript
能说明你的Javascript技术很烂的五个原因分析
2011/10/28 Javascript
jquery操作下拉列表、文本框、复选框、单选框集合(收藏)
2014/01/08 Javascript
JavaScript模板引擎用法实例
2015/07/10 Javascript
jQuery实现非常实用漂亮的select下拉菜单选择效果
2015/11/06 Javascript
jQuery css() 方法动态修改CSS属性
2016/09/25 Javascript
详解angularjs 关于ui-router分层使用
2017/06/12 Javascript
p5.js入门教程之小球动画示例代码
2018/03/15 Javascript
vue-cli3 DllPlugin 提取公用库的方法
2019/04/24 Javascript
vue.js iview打包上线后字体图标不显示解决办法
2020/01/20 Javascript
原生js+canvas实现验证码
2020/11/29 Javascript
python中使用sys模板和logging模块获取行号和函数名的方法
2014/04/15 Python
python学习教程之使用py2exe打包
2017/09/24 Python
python 读取DICOM头文件的实例
2018/05/07 Python
python爬虫URL重试机制的实现方法(python2.7以及python3.5)
2018/12/18 Python
Python Tkinter 简单登录界面的实现
2019/06/14 Python
Python基于gevent实现文件字符串查找器
2020/08/11 Python
Scrapy中如何向Spider传入参数的方法实现
2020/09/28 Python
python爬虫快速响应服务器的做法
2020/11/24 Python
真正了解CSS3背景下的@font face规则
2017/05/04 HTML / CSS
管理失职检讨书
2014/02/12 职场文书
感恩之星事迹材料
2014/05/03 职场文书
和谐家庭演讲稿
2014/05/24 职场文书
小学生自我评价100字(15篇)
2014/09/18 职场文书
小学优秀学生评语
2014/12/29 职场文书
英语教师个人工作总结
2015/02/09 职场文书
2015年信息宣传工作总结
2015/05/26 职场文书
贫民窟的百万富翁观后感
2015/06/09 职场文书
2016应届毕业生实习心得体会
2015/10/09 职场文书
Python Django模型详解
2021/10/05 Python
《LOL》“克隆大作战”久违归来 幻灵战队皮肤上线
2022/04/03 其他游戏