zoukankan      html  css  js  c++  java
  • Title

    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)
    
  • 相关阅读:
    Java文件操作大全
    struts2整合spring3整合成功但是spring无法注入
    简单理解xFire webservices
    分享几个常用过滤器
    mysql导sql脚本
    开源Jbpm4.4+ssh2+oracle10实现表单、流程自定义开发流程业务
    关于搭建FTP服务器
    chrome标签同步神器插件集装箱!
    记录java接口自动化模板优化
    java之封装日期工具类DateUtils
  • 原文地址:https://www.cnblogs.com/guotianbao/p/12789825.html
Copyright © 2011-2022 走看看