二叉查找树(binary search tree)——python实现

Python实现二叉查找树
本文介绍了二叉查找树的概念,包括如何进行遍历、插入、删除操作,以及计算树的高度、节点数,查找特定节点,找到树中的最大和最小关键字节点等。所有操作均以Python语言实现。

二叉查找树(binary search tree)

顾名思义二叉查找树中每个节点至多有两个子节点,并且还对存储于每个节点中的关键字值有个小小的要求,
即只要这个节点有左节点或右节点,那么其关键字值总的大于其左节点的关键字值,小于其右节点的关键字值,如下图:

因为树的结构特性,很适合使用递归的方式去操作,下面的实现中均是以递归的方式实现:

下面仅给出了python的实现,一是因为代码太长,二是python的实现是我对着C语言实现改过来的,基本没什么差别;
主要实现的方法有:
  • 遍历:
前序:preorder()——理根节点→处理左子树→处理右子树
中序:inorder()——处理左子树→处理根节点→处理右子树
后序:postorder()——处理左子树→处理右子树→处理根节点

  • 插入:

insert(key)——将关键字值为key的节点插入到适当的位置(注释里面的是非递归实现)

  • 删除:

delete(key)——将关键字值为key的节点从树中删掉(注释中给了说明)

  • 获取高度:

height()

  • 获取树中的节点数:

count()

  • 查找:

find(key)——查找关键字值为key的节点(二叉查找树的一个重要应用就是在查找中)

  • 获取树中最大key值节点和最key值小节点:

find_max()

find_min()

;;;

class tree_node:
    def __init__(self, key = None, left = None, right = None):
        self.key = key
        self.left = left
        self.right = right

class binary_search_tree:
    def __init__(self):
        self.root = None

    def preorder(self):
        print 'preorder: ',
        self.__preorder(self.root)
        print

    def __preorder(self, root):
        if not root:
            return
        print root.key,
        self.__preorder(root.left)
        self.__preorder(root.right)

    def inorder(self):
        print 'inorder: ',
        self.__inorder(self.root)
        print

    def __inorder(self, root):
        if not root:
            return
        self.__inorder(root.left)
        print root.key,
        self.__inorder(root.right)

    def postorder(self):
        print 'postorder: ',
        self.__postorder(self.root)
        print

    def __postorder(self, root):
        if not root:
            return
        self.__postorder(root.left)
        self.__postorder(root.right)
        print root.key,

    def insert(self, key):
        '''recursion'''
        self.root = self.__insert(self.root, key)
        
    def __insert(self, root, key):
        if not root:
            root = tree_node(key)
        else:
            if key < root.key:
                root.left = self.__insert(root.left, key)
            elif key > root.key:
                root.right = self.__insert(root.right, key)
            else:
                print key, 'is already in tree'
                
        return root
    
##non-recursion
##    def insert(self, key):
##        if not self.root:
##            self.root = tree_node(key)
##        else:
##            cur = self.root
##            while True:
##                if key < cur.key:
##                    if not cur.left:
##                        cur.left = tree_node(key)
##                        break
##                    cur = cur.left
##                elif key > cur.key:
##                    if not cur.right:
##                        cur.right = tree_node(key)
##                        break
##                    cur = cur.right
##                else:
##                    print key, 'in tree'
##                    break

    def height(self):
        return self.__height(self.root)
    
    def __height(self, root):
        if not root:
            return -1
        left_height = self.__height(root.left)
        right_height = self.__height(root.right)
        #return 1+(left_height if left_height>right_height else right_height)#这种方式是自己写的,后面两种高大上的是网上偷学的^_^
        #return 1+[left_height,right_height][left_height<right_height]
        return 1+(left_height>right_height and [left_height] or [right_height])[0]

    def count(self):
        '''elements in tree'''
        return self.__count(self.root)

    def __count(self, root):
        if not root:
            return 0
        return 1+self.__count(root.left)+self.__count(root.right)

    def delete(self, key):
        self.root = self.__delete(self.root, key)
##
##删除操作:
##首先找到删除的节点,
##1. 如果左右子树都不为空,则找到右子树中最小的节点min,用min.key代替删除节点的key,然后再到右子
##	 树中删除min节点,因为min没有左节点,所以删除它的话只需要用它的右节点代替它(如果有右节点);
##2. 如果左子树或者右子树不为空,则直接代替掉
##3. 如果左右均空即叶子节点,直接删掉
    def __delete(self, root, key):
        if not root:
            print 'not find key: ', key
        elif key < root.key:
            root.left = self.__delete(root.left, key)
        elif key > root.key:
            root.right = self.__delete(root.right, key)
        elif root.left and root.right: #found
            right_min = self.__find_min(self.root.right)
            root.key = right_min.key
            root.right = self.__delete(root.right, right_min.key)
        elif root.left:
            root = root.left
        elif root.right:
            root = root.right
        else:
            root = None #python的GC会在没有引用指向对象的时候销毁对象

        return root

    def find(self, key):
        node = self.__find(self.root, key)
        if not node:
            print 'not found'
        return node
        

    def __find(self, root, key):
        if not root:
            return None
        if key < root.key:
            return self.__find(root.left, key)
        elif key > root.key:
            return self.__find(root.right, key)
        else:
            return root

    def find_min(self):
        return self.__find_min(self.root)

    def __find_min(self, root):
        if not root.left:
            return root
        return self.__find_min(root.left)

    def find_max(self):
        return self.__find_max(self.root)

    def __find_max(self, root):
        if not root.right:
            return root
        return self.__find_max(root.right)


def main():
    import random
    root = binary_search_tree()
    for i in random.sample([j for j in range(1, 100)], 5):
        root.insert(i)
    print 'insert: '
    root.insert(78)
    root.insert(101)
    root.insert(14)
    
    root.preorder()
    root.inorder()
    root.postorder()
    print 'height: ', root.height()
    print 'count: ', root.count()
    print 'min: ', root.find_min().key
    print 'max: ', root.find_max().key
    
    print 'delete: '
    root.delete(101)
    root.delete(12)
    
    root.preorder()
    root.inorder()
    root.postorder()
    print root.find(71)
    print root.find(78)
    print 'height: ', root.height()
    print 'count: ', root.count()
    print 'min: ', root.find_min().key
    print 'max: ', root.find_max().key
    
if __name__ == '__main__':
    main()
    



### 如何在 Python实现二叉搜索树节点的删除操作 以下是基于提供的引用内容以及专业知识,给出的一个完整的 Python 实现方案: #### 节点类定义 为了构建二叉搜索树 (Binary Search Tree, BST),首先需要定义一个 `Node` 类来表示单个节点。 ```python class Node: def __init__(self, key): self.left = None self.right = None self.val = key ``` #### 二叉搜索树类定义 接着,创建一个用于管理整棵树的类 `BinarySearchTree`。此部分参考了相关内容[^2]。 ```python class BinarySearchTree: def __init__(self): self.root = None ``` #### 插入方法 插入新节点的操作遵循标准的二叉搜索树规则:左子节点值小于父节点值,右子节点值大于父节点值。 ```python def insert(self, node, val): if not node: return Node(val) if val < node.val: node.left = self.insert(node.left, val) elif val > node.val: node.right = self.insert(node.right, val) return node ``` #### 查找最小值函数 删除过程中可能需要用到寻找某个节点的后继(即其右子树中最左侧的叶子),这部分可以单独封装成辅助函数。 ```python def find_min(self, node): current = node while(current.left is not None): current = current.left return current ``` #### 删除节点的核心逻辑 删除分为三种情况讨论: 1. **目标节点无任何子节点** —— 直接移除; 2. **目标节点只有一个子节点** —— 将该子节点提升至被删位置; 3. **目标节点有两个子节点** —— 找到右子树中的最小值替代当前节点,并递归地从原位置删除这个最小值节点。 具体代码如下所示: ```python def delete_node(self, root, key): if not root: return root # 如果键值小于根节点,则继续向左子树查找并执行删除动作 if key < root.val: root.left = self.delete_node(root.left, key) # 同理对于右侧的情况也是如此处理 elif(key > root.val): root.right = self.delete_node(root.right, key) else: # 当前节点正好是要删除的目标对象时进入下面分支判断 if root.left is None : temp = root.right root = None return temp elif root.right is None : temp = root.left root = None return temp # 若存在两个孩子结点的话就取右边最小子作为新的顶替者 temp = self.find_min(root.right) # 把那个找到的小孩赋给现在的root的位置上 root.val = temp.val # 接着再把原先那条路径上的重复元素去掉即可完成整体流程 root.right = self.delete_node(root.right , temp.val) return root ``` 以上就是整个删除过程的具体实现方式[^1]。 #### 测试用例 最后提供一段简单的测试脚本验证上述功能是否正常工作。 ```python if __name__ == "__main__": bst = BinarySearchTree() keys = [50, 30, 70, 20, 40, 60, 80] for key in keys: bst.root = bst.insert(bst.root, key) print("Inorder traversal of the constructed tree:") # Assume an inorder function exists here to display elements. print("\nDelete 20") bst.root = bst.delete_node(bst.root, 20) # Again assume a method prints updated structure after deletion. ``` --- ###
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值