AVL、B树和B+树

举报
William 发表于 2024/11/29 09:31:34 2024/11/29
【摘要】 AVL树 简介AVL树是一种严格平衡的二叉搜索树,即对于每个节点,其左子树和右子树的高度差不超过1。这保证了AVL树的平均查找、插入、删除操作时间复杂度为O(log n)。 应用场景常用于需要快速查询的数据结构,如数据库索引实现。 原理解释旋转操作:为了保持AVL性质,需要在插入或删除节点后通过旋转来调整树的平衡状态。旋转分为四种:单右旋、单左旋、双右旋(先左后右)、双左旋(先右后左)。算...

AVL树

简介

AVL树是一种严格平衡的二叉搜索树,即对于每个节点,其左子树和右子树的高度差不超过1。这保证了AVL树的平均查找、插入、删除操作时间复杂度为O(log n)。

应用场景

常用于需要快速查询的数据结构,如数据库索引实现。

原理解释

  • 旋转操作:为了保持AVL性质,需要在插入或删除节点后通过旋转来调整树的平衡状态。旋转分为四种:单右旋、单左旋、双右旋(先左后右)、双左旋(先右后左)。

  • 算法流程

    1. 插入或删除节点。
    2. 从该节点向上回溯,更新每个节点的平衡因子(左子树高度 - 右子树高度)。
    3. 如有必要,执行旋转操作以恢复平衡。
class Node:
    def __init__(self, key):
        self.key = key
        self.height = 1
        self.left = None
        self.right = None

def insert(root, key):
    if not root:
        return Node(key)
    elif key < root.key:
        root.left = insert(root.left, key)
    else:
        root.right = insert(root.right, key)

    root.height = 1 + max(get_height(root.left), get_height(root.right))
    
    balance = get_balance(root)
    
    # Left heavy
    if balance > 1:
        if key < root.left.key:  # Left-Left case
            return right_rotate(root)
        else:  # Left-Right case
            root.left = left_rotate(root.left)
            return right_rotate(root)
    
    # Right heavy
    if balance < -1:
        if key > root.right.key:  # Right-Right case
            return left_rotate(root)
        else:  # Right-Left case
            root.right = right_rotate(root.right)
            return left_rotate(root)
    
    return root

def left_rotate(z):
    y = z.right
    T2 = y.left
    y.left = z
    z.right = T2
    z.height = 1 + max(get_height(z.left), get_height(z.right))
    y.height = 1 + max(get_height(y.left), get_height(y.right))
    return y

def right_rotate(z):
    y = z.left
    T3 = y.right
    y.right = z
    z.left = T3
    z.height = 1 + max(get_height(z.left), get_height(z.right))
    y.height = 1 + max(get_height(y.left), get_height(y.right))
    return y

def get_height(root):
    if not root:
        return 0
    return root.height

def get_balance(root):
    if not root:
        return 0
    return get_height(root.left) - get_height(root.right)

# Testing the AVL tree insertion
root = None
keys = [10, 20, 30, 40, 50, 25]
for key in keys:
    root = insert(root, key)

B树

简介

B树是一种自平衡的多路搜索树,广泛用于文件系统和数据库中。它允许在内部节点存储多个子树和数据,适合外存储访问。

应用场景

应用于数据库系统、文件系统等需要读/写大量数据并且对访问速度要求较高的场景。

原理解释

  • 节点特性:每个节点可以包含多个键和子节点。
  • 平衡:所有叶子节点的深度相同。
  • 分裂和合并:当插入或删除导致节点过多或过少时,节点会分裂或合并。
class BTreeNode:
    def __init__(self, leaf=False):
        self.leaf = leaf
        self.keys = []
        self.children = []

class BTree:
    def __init__(self, t):
        self.root = BTreeNode(leaf=True)
        self.t = t  # Minimum degree

    def search(self, k, x=None):
        if isinstance(x, BTreeNode):
            i = 0
            while i < len(x.keys) and k > x.keys[i]:
                i += 1
            if i < len(x.keys) and k == x.keys[i]:
                return (x, i)
            elif x.leaf:
                return None
            else:
                return self.search(k, x.children[i])
        else:
            return self.search(k, self.root)

    def insert(self, k):
        root = self.root
        if len(root.keys) == (2 * self.t) - 1:
            temp = BTreeNode()
            self.root = temp
            temp.children.insert(0, root)
            self.split_child(temp, 0)
            self.insert_non_full(temp, k)
        else:
            self.insert_non_full(root, k)

    def split_child(self, x, i):
        t = self.t
        y = x.children[i]
        z = BTreeNode(leaf=y.leaf)
        x.children.insert(i + 1, z)
        x.keys.insert(i, y.keys[t - 1])
        z.keys = y.keys[t:(2 * t) - 1]
        y.keys = y.keys[0:t - 1]

        if not y.leaf:
            z.children = y.children[t:2 * t]
            y.children = y.children[0:t - 1]

    def insert_non_full(self, x, k):
        i = len(x.keys) - 1
        if x.leaf:
            x.keys.append(None)
            while i >= 0 and k < x.keys[i]:
                x.keys[i + 1] = x.keys[i]
                i -= 1
            x.keys[i + 1] = k
        else:
            while i >= 0 and k < x.keys[i]:
                i -= 1
            i += 1
            if len(x.children[i].keys) == (2 * self.t) - 1:
                self.split_child(x, i)
                if k > x.keys[i]:
                    i += 1
            self.insert_non_full(x.children[i], k)

# Testing the B-tree insertion
btree = BTree(3)
elements = [10, 20, 5, 6, 12, 30, 7, 17]
for elem in elements:
    btree.insert(elem)

B+树

简介

B+树是B树的变体,主要区别在于所有有效信息都存在叶子节点,内部节点只作为索引使用。此外,叶子节点彼此间用指针连接形成链表,以便于范围查询。

应用场景

B+树被普遍用于数据库索引、文件系统中,尤其适用于频繁的范围查询操作。

原理解释

  • 节点结构:内部节点仅保存索引,而数据全在叶子节点中。
  • 顺序访问指针:叶子节点通过链表相连,支持高效的顺序读取。
# The implementation of B+ Tree is complex for a simple example.
# Here is a basic structure outline, actual implementations may vary.

class BPlusTreeNode:
    def __init__(self, leaf=False):
        self.leaf = leaf
        self.keys = []
        self.values = []
        self.parent = None
        self.next = None

class BPlusTree:
    def __init__(self, order=4):
        self.root = BPlusTreeNode(True)
        self.order = order

    # Insert method, Split method, Search method would go here.
    # For brevity, these methods are complex and aren't shown fully here.

# Testing the B+ tree insertion
bplustree = BPlusTree(order=3)
# Assume insert method and other required methods are implemented properly.
# elements = [10, 20, 5, 6, 12, 30, 7, 17]
# for elem in elements:
#     bplustree.insert(elem)

总结与未来展望

这三种树形数据结构各有优劣,AVL树适用于内存中的快速数据访问,B树和B+树更适合磁盘存储环境下的大数据访问。在未来,随着大数据和数据库技术的发展,这些树结构可能会结合新的硬件架构进行进一步优化,如针对SSD的特殊优化或在分布式环境下的应用。

材料链接

这些链接提供了更详细的理论背景和实现细节,可以帮助深入理解和实现这些数据结构。

【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。