平衡二叉搜索树

63 阅读4分钟

二叉搜索树

添加、删除节点可能导致二叉搜索树退化成链表

那么要如何改进二叉搜索树呢

节点的添加、删除顺序是无法限制的,也就是随机的。

那么改进方案是:在节点的添加、删除操作之后,想办法让二叉搜索树恢复平衡(减小树的高度)。

如果接着继续调整节点的位置,完全可以达到理想平衡,但是付出的代价可能会比较大。如果调整次数太多,反而增加了时间复杂度。

所以比较合适的方案是:用尽量少的调整次数达到适度平衡

一颗达到适度平衡的二叉搜索树,可以称之为:平衡二叉搜索树

平衡二叉搜索树 BBST(Balanced Binary Search Tree)

常见的平衡二叉搜索树

1、AVL树

2、红黑树

一般也称它们为:自平衡的二叉搜索树(Self-balancing Binary Search Tree)

AVL树

平衡因子(Balance Factor):某结点的左右子树的高度差

AVL树的特点:

1、每个节点的平衡因子只可能是 1、0、-1(绝对值 ≤ 1,如果超过 1,称之为“失衡”)

2、每个节点的左右子树高度差不超过1

3、搜索、添加、删除的时间复杂度是 O(logn)

添加导致的失衡

1.png

LL– 右旋转(单旋)

2.png

RR – 左旋转(单旋)

3.png

LR – RR左旋转,LL右旋转(双旋)

4.png

RL – LL右旋转,RR左旋转(双旋)

5.png

删除导致的失衡

LL– 右旋转(单旋)

截屏2023-10-13 16.20.09.png

RR – 左旋转(单旋)

截屏2023-10-13 16.20.20.png

LR – RR左旋转,LL右旋转(双旋)

截屏2023-10-13 16.20.29.png

RL – LL右旋转,RR左旋转(双旋)

截屏2023-10-13 16.20.35.png

二叉搜索树实现

class BST<T: Comparable>: BinaryTree<T> {
    // MARK: 添加
    func add(_ element: T) {
        if root == nil { // 添加的第一个元素(根结点)
            root = createNode(element: element)
            size = 1
            afterAdd(root!)
            return
        }
        var node = root
        var parent = root
        var cmp = 0
        while node != nil {
            parent = node
            if element < node!.element {
                node = node!.left
                cmp = -1
            } else if element > node!.element {
                node = node!.right
                cmp = 1
            } else {
                node!.element = element
                cmp = 0
            }
        }
        
        let newNode = createNode(element: element, parent: parent)
        if cmp > 0 {
            parent!.right = newNode
        } else {
            parent!.left = newNode
        }
        size += 1
        afterAdd(newNode)
    }
    
    // MARK: 添加之后调整平衡
    func afterAdd(_ node: Node<T>) {
        
    }
    
    // MARK: 删除之后调整平衡
    func afterRemove(_ node: Node<T>) {
        
    }
    
    // MARK: 给定结点是否是该二叉树的结点
    func contains(_ element: T) -> Bool {
        return node(element) != nil
    }
    
    // MARK: 删除
    func remove(_ element: T) {
        remove(node: node(element))
    }
    
    private func remove(node: Node<T>?) {
        guard var node = node else { return }
        size -= 1
        if node.hasTwoChildren() {
            // 度为2的结点 找到前驱或者后继结点,覆盖原结点的值,再删除前驱或者后继结点
            // 如果一个结点的度为2,那么它的前驱或者后继结点的度为0或1
            
            // 找到后继节点
            let next = successor(node)
            // 用后继节点的值覆盖度为2的节点的值
            node.element = next!.element
            // 删除后继节点
            node = next!
        }
        
        // 删除node节点(node的度必然是1或者0)
        let replacement = node.left != nil ? node.left : node.right
        // 度为1的结点
        if replacement != nil {
            replacement!.parent = node.parent
            if node.parent == nil { // node是度为1的节点并且是根节点
                root = replacement
            } else if node === node.parent!.left {
                node.parent!.left = replacement
            } else { // node == node.parent.right
                node.parent!.right = replacement
            }
            // 删除节点之后的处理
            afterRemove(node)
        } else if node.parent == nil { // node是叶子节点并且是根节点
            root = nil
            // 删除节点之后的处理
            afterRemove(node)
        } else { // node是叶子节点,但不是根节点
            if node === node.parent!.left {
                node.parent!.left = nil
            } else { // node == node.parent.right
                node.parent!.right = nil
            }
            // 删除节点之后的处理
            afterRemove(node)
        }
    }
    
    // MARK: 根据结点元素查找结点
    private func node(_ element: T) -> Node<T>? {
        var node = root
        while node != nil {
            if node!.element == element {
                return node
            } else if node!.element > element {
                node = node!.left
            } else {
                node = node!.right
            }
        }
        return nil
    }
}

AVL树实现


class AVLTree<T: Comparable>: BST<T> {
    override func afterAdd(_ node: BST<T>.Node<T>) {
        var n = node.parent
        while n != nil {
            if isBalanced(n!) {
                // 更新高度
                updateHeight(n!)
            } else {
                // 恢复平衡
                rebalance(n!)
                break
            }
            n = n!.parent
        }
    }
    
    override func afterRemove(_ node: BST<T>.Node<T>) {
        var n = node.parent
        while n != nil {
            if isBalanced(n!) {
                // 更新高度
                updateHeight(n!)
            } else {
                // 恢复平衡
                rebalance(n!)
            }
            n = n!.parent
        }
    }
    
    //MARK: 结点是否平衡
    private func isBalanced(_ node: Node<T>) -> Bool {
        return abs((node as! AVLNode).balanceFactor()) <= 1
    }
    
    //MARK: 更新高度
    private func updateHeight(_ node: Node<T>) {
        (node as! AVLNode).updateHeight()
    }
    
    //MARK: 恢复平衡
    //MARK: grand 高度最低的那个不平衡结点
    private func rebalance(_ grand: Node<T>) {
        let parent = (grand as! AVLNode).tallerChild() as! AVLNode
        let node = parent.tallerChild() as! AVLNode
        if parent.isLeftChild() { // L
            if node.isLeftChild() { // LL
                rotateRight(grand)
            } else { // LR
                rotateLeft(parent)
                rotateRight(grand)
            }
        } else { // R
            if node.isLeftChild() { // RL
                rotateRight(parent)
                rotateLeft(grand)
            } else { // RR
                rotateLeft(grand)
            }
        }
    }
    
    private func rotateLeft(_ grand: Node<T>) {
        let parent = grand.right as! AVLNode
        let child = parent.left
        grand.right = child
        parent.left = grand
        afterRotate(grand: grand, parent: parent, child: child)
    }
    
    private func rotateRight(_ grand: Node<T>) {
        let parent = grand.left as! AVLNode
        let child = parent.right
        grand.left = child
        parent.right = grand
        afterRotate(grand: grand, parent: parent, child: child)
    }
    
    private func afterRotate(grand: Node<T>, parent: Node<T>, child: Node<T>?) {
        // 让parent称为子树的根节点
        parent.parent = grand.parent
        if grand.isLeftChild() {
            grand.parent?.left = parent
        } else if grand.isRightChild() {
            grand.parent?.right = parent
        } else {
            root = parent
        }
        // 更新child的parent
        child?.parent = grand
        // 更新grand的parent
        grand.parent = parent
        
        // 更新高度
        updateHeight(grand)
        updateHeight(parent)
    }
    
    override func createNode(element: T, parent: BinaryTree<T>.Node<T>? = nil) -> BinaryTree<T>.Node<T> {
        return AVLNode(element: element, parent: parent)
    }
    
    private class AVLNode: Node<T> {
        var height = 1
        
        // 平衡因子
        func balanceFactor() -> Int {
            let leftHeight = self.left == nil ? 0 : (self.left as! AVLNode).height
            let rightHeight = self.right == nil ? 0 : (self.right as! AVLNode).height
            return leftHeight - rightHeight
        }
        
        // 更新高度
        func updateHeight() {
            let leftHeight = self.left == nil ? 0 : (self.left as! AVLNode).height
            let rightHeight = self.right == nil ? 0 : (self.right as! AVLNode).height
            height = 1 + max(leftHeight, rightHeight)
        }
        
        // 高度更高的子结点
        func tallerChild() -> Node<T>? {
            let leftHeight = self.left == nil ? 0 : (self.left as! AVLNode).height
            let rightHeight = self.right == nil ? 0 : (self.right as! AVLNode).height
            if leftHeight > rightHeight {
                return self.left
            }
            if leftHeight < rightHeight {
                return self.right
            }
            return isLeftChild() ? self.left : self.right
        }
    }
}

总结:

截屏2023-10-13 16.27.29.png