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读文件逐行处理的示例代码分享
Dec 27 Python
Python操作SQLite简明教程
Jul 10 Python
一百多行python代码实现抢票助手
Sep 25 Python
Python实现字典排序、按照list中字典的某个key排序的方法示例
Dec 18 Python
利用Pandas和Numpy按时间戳将数据以Groupby方式分组
Jul 22 Python
python实现证件照换底功能
Aug 20 Python
python多线程分块读取文件
Aug 29 Python
Python爬虫爬取煎蛋网图片代码实例
Dec 16 Python
Python tkinter常用操作代码实例
Jan 03 Python
Python开发之基于模板匹配的信用卡数字识别功能
Jan 13 Python
解决pycharm每次打开项目都需要配置解释器和安装库问题
Feb 26 Python
python openCV自制绘画板
Oct 27 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 验证码的实现代码
2011/07/17 PHP
基于Zend的Config机制的应用分析
2013/05/02 PHP
一个经典的PHP验证码类分享
2014/11/18 PHP
php获取发送给用户的header信息的方法
2015/03/16 PHP
onpropertypchange
2006/07/01 Javascript
Javascript实现的分页函数
2006/12/22 Javascript
基于jquery的修改当前TAB显示标题的代码
2010/12/11 Javascript
JavaScript高级程序设计(第3版)学习笔记10 再访js对象
2012/10/11 Javascript
Function.prototype.bind用法示例
2013/09/16 Javascript
在Google 地图上实现做的标记相连接
2015/01/05 Javascript
简介JavaScript中substring()方法的使用
2015/06/06 Javascript
javascript先序遍历DOM树的方法
2016/02/27 Javascript
jQuery防止重复绑定事件的解决方法
2016/05/14 Javascript
JavaScript中Array的实用操作技巧分享
2016/09/11 Javascript
基于vuejs实现一个todolist项目
2017/04/11 Javascript
使用jquery+iframe做一个ajax上传效果(实例)
2017/08/24 jQuery
es6基础学习之解构赋值
2018/12/10 Javascript
用element的upload组件实现多图片上传和压缩的示例代码
2019/02/12 Javascript
详解mpvue开发微信小程序基础知识
2019/09/23 Javascript
微信小程序实现下滑到底部自动翻页功能
2020/03/07 Javascript
[46:04]Liquid vs VP Supermajor决赛 BO 第四场 6.10
2018/07/05 DOTA
python实现周期方波信号频谱图
2018/07/21 Python
解决python中os.listdir()函数读取文件夹下文件的乱序和排序问题
2018/10/17 Python
创建Django项目图文实例详解
2019/06/06 Python
python pycharm最新版本激活码(永久有效)附python安装教程
2020/09/18 Python
解决keras backend 越跑越慢问题
2020/06/18 Python
HTML5 层的叠加的实现
2020/07/07 HTML / CSS
viagogo波兰票务平台:演唱会、体育比赛、戏剧门票
2018/04/23 全球购物
Kathmandu新西兰官网:新西兰户外运动品牌
2019/07/27 全球购物
澳大利亚领先的女帽及配饰公司:Morgan&Taylor
2019/12/01 全球购物
UNIX操作系统结构由哪几部分组成
2016/02/17 面试题
经理职责范文
2013/11/08 职场文书
2014年小学植树节活动方案
2014/03/02 职场文书
2015年司机工作总结
2015/04/23 职场文书
python制作图形界面的2048游戏, 基于tkinter
2021/04/06 Python
使用Springboot实现健身房管理系统
2021/07/01 Java/Android