Bineary Search Tree知识点总结

169 阅读2分钟

二叉查找树

1. 定义

二叉查找树(Binary Search Tree),也称二叉搜索树、有序二叉树(ordered binary tree),排序二叉树(orted binary tree),是指一棵空树或者具有下列性质的二叉树:

  • 若任意节点的左子树不空,则左子树上所有节点的值均小于它的根节点的值;
  • 若任意节点的右子树不空,则右子树上所有节点的值均大于它的根节点的值;
  • 任意节点的左、右子树也分别为二叉查找树;
  • 没有键值相等的节点

二叉查找树相比于其他数据结构的优势在于查找、插入的时间复杂度较低,均为O(log n)


2. 基本操作

1. 查找

在二叉树b中查找x的过程为:

  1. 若b是空树,则搜索失败,否则:
  2. 若x等于b的根节点的数据域之值,则查找成功;否则:
  3. 若x小于b的根节点的数据域之值,则递归搜索左子树;否则:
  4. 递归查找右子树

def searchBST(root, val):
    
    """
    :type root: TreeNode
    :type val: int
    :rtype: TreeNode
    """
    if not root:
        return None

    if root.val == val:
        return root

    if root.val > val:
        return searchBST(root.left, val)
    else:
        return searchBST(root.right, val)

Average case: O(H)/O(logN), H is a tree height.
Worst case: O(N)

Sample code: Here


2. 插入

向一个二叉搜索树b中插入一个节点s的算法,过程为:

  1. 若b是空树,则将s所指结点作为根节点插入,否则:
  2. 若s.val等于b的根节点的数据域之值,则返回,否则:
  3. 若s.val小于b的根节点的数据域之值,则把s所指节点插入到左子树中,否则:
  4. 把s所指节点插入到右子树中**(新插入节点总是叶子节点)**
def insertIntoBST(root, val):
    """
    :type root: TreeNode
    :type val: int
    :rtype: TreeNode
    """
    if root == None:
        return TreeNode(val)

    if root.val > val:
        root.left = self.insertIntoBST(root.left, val)
    elif root.val < val:
        root.right =  self.insertIntoBST(root.right, val)

    return root

Average case: O(logN)
Worst case: O(N)

Sample code: Here


3. 删除

删除分三种情况讨论

  1. 如果是leaf,直接删除
  2. 如果有一个子节点,用子节点替换
  3. 如果有两个子节点,找到successor(right tree中最小的node),用successor替换,并把successor删除
class Solution(object):
    # The functions to find successor and predecessor are based on the assumption that root has two children.
    def successor(self, root):
        root = root.right
        while root.left:
            root = root.left
        return root
    def predecessor(self, root):
        root = root.left
        while root.right:
            root = root.right
        return root

    def deleteNode(self, root, key):
        """
        :type root: TreeNode
        :type key: int
        :rtype: TreeNode
        """
        if not root:
            return None

        if root.val > key:
            root.left = self.deleteNode(root.left, key)
        elif root.val < key:
            root.right = self.deleteNode(root.right, key)
        # delete the current node
        else:
            # the node is a leaf
            if not root.left and not root.right:
                root = None
            # the node has two children
            elif root.right:
                successor = self.successor(root)
                root.val = successor.val
                root.right = self.deleteNode(root.right, root.val)
            # the node has only left child
            elif root.left:
                predecessor = self.predecessor(root)
                root.val = predecessor.val
                predecessor = None
                root.left = self.deleteNode(root.left, root.val)
        return root

Average case: O(logN)
Worst case: O(N)

Sample code: Here


4. 遍历

Inorder Traversal保证升序输出

Algorithm:

def traverse_binary_tree(root):
    if root is None:
        return
    traverse_binary_tree(root.left)
    print(root.value)
    traverse_binary_tree(root.right)

5. Find inorder successor of p in BST

  1. 如果p.right不为None: 直接找successor; 否则
  2. 进行inorder traversal,找到p的successor
 class Solution(object):
     def inorderSuccessor(self, root, p):
         """
         :type root: TreeNode
         :type p: TreeNode
         :rtype: TreeNode
         """
         # if successor in the lower right tree
         if p.right:
             p = p.right
             while p.left:
                 p = p.left
             return p

         # if successor in the upper tree
         stack = []
         inorder = float('inf')

         while stack or root:

             while root:
                 stack.append(root)
                 root = root.left

             root = stack.pop()
             if inorder == p.val:
                 return root
             inorder = root.val

             root = root.right

         return None