📜  二叉搜索树和二叉堆的区别(1)

📅  最后修改于: 2023-12-03 15:06:19.754000             🧑  作者: Mango

二叉搜索树和二叉堆的区别

二叉搜索树(Binary Search Tree)和二叉堆(Binary Heap)都是常用的数据结构,但在某些情况下,它们的应用场景是不同的,因此需要根据具体场景选择不同的数据结构。

二叉搜索树

二叉搜索树是一种有序的二叉树,它满足以下条件:

  1. 左子树上所有节点的值均小于根节点的值。
  2. 右子树上所有节点的值均大于根节点的值。
  3. 左右子树也分别为二叉搜索树。

二叉搜索树的插入、查找和删除操作都可以在 O(log n) 的时间复杂度内完成,因此在需要频繁插入、删除、查找元素的情况下,使用二叉搜索树可以获得比较高的性能。

以下是二叉搜索树的示例代码:

class TreeNode:
    def __init__(self, val):
        self.val = val
        self.left = None
        self.right = None

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

    def insert(self, val):
        if not self.root:
            self.root = TreeNode(val)
            return

        current = self.root
        while current:
            if val < current.val:
                if not current.left:
                    current.left = TreeNode(val)
                    return
                current = current.left
            else:
                if not current.right:
                    current.right = TreeNode(val)
                    return
                current = current.right

    def search(self, val):
        current = self.root
        while current:
            if val == current.val:
                return current
            elif val < current.val:
                current = current.left
            else:
                current = current.right
        return None

    def delete(self, val):
        node, parent = self._search_node(val)
        if not node:
            return

        if node.left and node.right:
            successor = node.right
            while successor.left:
                successor = successor.left
            node.val = successor.val
            node, parent = successor, self._search_parent(successor.val)

        if node.left or node.right:
            child = node.left or node.right
            if node == parent.left:
                parent.left = child
            else:
                parent.right = child
        else:
            if node == parent.left:
                parent.left = None
            else:
                parent.right = None

    def _search_node(self, val):
        current = self.root
        parent = None
        while current:
            if val == current.val:
                return current, parent
            elif val < current.val:
                parent, current = current, current.left
            else:
                parent, current = current, current.right
        return None, None

    def _search_parent(self, val):
        current = self.root
        parent = None
        while current:
            if val == current.val:
                return parent
            elif val < current.val:
                parent, current = current, current.left
            else:
                parent, current = current, current.right
        return None
二叉堆

二叉堆是一种完全二叉树,它分为两种类型:最大堆和最小堆。最大堆是一种满足以下条件的二叉堆:

  1. 任意节点的值都不大于其父节点的值。
  2. 左右子树也分别为最大堆。

最小堆则是任意节点的值都不小于其父节点的值,并且左右子树也分别为最小堆。

二叉堆常用于实现优先队列和堆排序,其插入、删除、查找最大(最小)元素等操作的时间复杂度均为 O(log n)。

以下是最大堆的示例代码:

class BinaryHeap:
    def __init__(self):
        self.heap = []

    def insert(self, val):
        self.heap.append(val)
        self._sift_up(len(self.heap) - 1)

    def delete_max(self):
        if len(self.heap) == 1:
            return self.heap.pop()

        maxval = self.heap[0]
        self.heap[0] = self.heap.pop()
        self._sift_down(0)
        return maxval

    def _sift_up(self, index):
        parent = (index - 1) // 2
        if parent >= 0 and self.heap[index] > self.heap[parent]:
            self.heap[index], self.heap[parent] = self.heap[parent], self.heap[index]
            self._sift_up(parent)

    def _sift_down(self, index):
        left, right = index * 2 + 1, index * 2 + 2
        largest = index
        if left < len(self.heap) and self.heap[left] > self.heap[largest]:
            largest = left
        if right < len(self.heap) and self.heap[right] > self.heap[largest]:
            largest = right
        if largest != index:
            self.heap[index], self.heap[largest] = self.heap[largest], self.heap[index]
            self._sift_down(largest)
区别

二叉搜索树和二叉堆的最大区别在于它们的节点值排列方式不同。在二叉搜索树中,左子树上所有节点的值均小于根节点的值,右子树上所有节点的值均大于根节点的值。而在二叉堆中,子树上的所有节点的值都不大于(或不小于)父节点的值。

因此,二叉搜索树适合需要快速查找和删除某个特定元素的场景。而二叉堆适合需要快速查找和删除最大(或最小)元素的场景。二叉搜索树的插入操作的时间复杂度是 O(log n),删除操作的时间复杂度也是 O(log n)。而二叉堆的插入、删除、查找最大(最小)元素等操作的时间复杂度均为 O(log n)。

总之,二叉搜索树和二叉堆在不同场景下各有优劣,需要结合具体需求进行选择。