平衡二叉樹(AVL)python實現

AVL樹是一種特殊的二叉搜索樹 (BST樹),數據極端情況下, 二叉搜索樹會退化成爲單鏈表,但是AVL樹通過旋轉操作規避了這個問題。

查找平均複雜度:O(logn)

# AVL樹不適於刪除的情況
class AVLTreeNode(object):
    def __init__(self, data):
        self.data = data  # 數據
        self.left: AVLTreeNode = None  # 左子樹
        self.right: AVLTreeNode = None  # 右子樹
        self.height = 1  # 樹高度


def get_data(node: AVLTreeNode):
    return node.data


def set_data(node: AVLTreeNode, data):
    node.data = data


# 獲得樹形結構
def get_left_node(node: AVLTreeNode):
    return node.left


def get_right_node(node: AVLTreeNode):
    return node.right


def get_height(node: AVLTreeNode):
    if node is None:
        return 0
    return node.height


def get_max_node(node: AVLTreeNode):
    temp_node = node
    if temp_node.right is not None:
        return get_max_node(temp_node.right)
    else:
        return temp_node


def get_min_node(node: AVLTreeNode):
    temp_node = node
    if temp_node.left is not None:
        return get_min_node(temp_node.left)
    else:
        return temp_node


def get_node(node: AVLTreeNode, data):
    temp_node: AVLTreeNode = node
    while temp_node:
        if data < temp_node.data:
            temp_node = temp_node.left
        elif data > temp_node.data:
            temp_node = temp_node.right
        else:
            return temp_node
    return None


# 右旋:先記錄待旋轉節點的左節點,然後將左節點的right指向待旋轉節點即可
def right_rotate(node: AVLTreeNode):
    head_node: AVLTreeNode = node.left
    node.left = head_node.right  # 將父節點的右側放在待旋轉節點的左側
    head_node.right = node  # 將父節點的右指針指向待旋轉節點
    node.height = max(get_height(node.left), get_height(node.right)) + 1
    head_node.height = max(get_height(head_node.left), get_height(head_node.right)) + 1
    return head_node


def left_rotate(node: AVLTreeNode):
    head_node: AVLTreeNode = node.right
    node.right = head_node.left
    head_node.left = node
    node.height = max(get_height(node.left), get_height(node.right)) + 1
    head_node.height = max(get_height(head_node.left), get_height(head_node.right)) + 1
    return head_node


# 先左旋,再右旋
def left_right_rotate(node: AVLTreeNode):
    son_node = left_rotate(node.left)
    node.left = son_node
    return right_rotate(node)


def right_left_rotate(node: AVLTreeNode):
    son_node = right_rotate(node.right)
    node.right = son_node
    return left_rotate(node)


# 左子樹與右子樹差距最大爲1,否則及時調整
def adjust_height(node: AVLTreeNode):
    if get_height(node.right) - get_height(node.left) > 1:
        if get_height(node.right.right) > get_height(node.right.left):
            node = left_rotate(node)
        else:
            node = right_left_rotate(node)
    elif get_height(node.left) - get_height(node.right) > 1:
        if get_height(node.left.left) > get_height(node.left.right):
            node = right_rotate(node)
        else:
            node = left_right_rotate(node)
    else:
        pass
    return node


def insert_node(node: AVLTreeNode, data):
    if node is None:
        return AVLTreeNode(data)
    if (node.data is not None) and (data < node.data):  # 向左插入
        node.left = insert_node(node.left, data)
        node.height = max(get_height(node.left), get_height(node.right)) + 1
        node = adjust_height(node)
    elif (node.data is not None) and (data > node.data):  # 向右插入
        node.right = insert_node(node.right, data)
        node.height = max(get_height(node.left), get_height(node.right)) + 1
        node = adjust_height(node)
    else:
        print('Can not insert same value')
    return node


def delete_node(node: AVLTreeNode, data):
    if node is None:
        return None
    if (node is not None) and (data < node.data):  # 左側查詢
        node.left = delete_node(node.left, data)
        node = adjust_height(node)
    elif (node is not None) and (data > node.data):  # 右側查詢
        node.right = delete_node(node.right, data)
        node = adjust_height(node)
    else:  # 在這裏刪除
        if (node.left is not None) and (node.right is not None):  # 左右節點都不爲空
            node.data = get_min_node(node.right).data
            node.right = delete_node(node.right, node.data)
        elif node.left is not None:  # 左節點不爲空,右節點爲空
            node = node.left
        else:  # 左節點爲空,右節點未知
            node = node.right
    if node is not None:
        node.height = max(get_height(node.left), get_height(node.right)) + 1
        adjust_height(node)
    return node


def get_all(node: AVLTreeNode):
    values = []

    def add_values(values, node: AVLTreeNode):
        if node is not None:
            values = add_values(values, node.left)
            values.append(node.data)
            values = add_values(values, node.right)
        return values

    return add_values(values, node)


def main():
    root = AVLTreeNode(10)
    number_list = (3, 2, 1, 4, 5, 6, 7, 15, 26, 17)
    for number in number_list:
        root = insert_node(root, number)
    all_values = get_all(root)
    del_note = delete_node(root, 3)
    all_values = get_all(root)
    pass


if __name__ == '__main__':
    main()

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章