📅  最后修改于: 2023-12-03 15:06:19.754000             🧑  作者: Mango
二叉搜索树(Binary Search Tree)和二叉堆(Binary Heap)都是常用的数据结构,但在某些情况下,它们的应用场景是不同的,因此需要根据具体场景选择不同的数据结构。
二叉搜索树是一种有序的二叉树,它满足以下条件:
二叉搜索树的插入、查找和删除操作都可以在 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
二叉堆是一种完全二叉树,它分为两种类型:最大堆和最小堆。最大堆是一种满足以下条件的二叉堆:
最小堆则是任意节点的值都不小于其父节点的值,并且左右子树也分别为最小堆。
二叉堆常用于实现优先队列和堆排序,其插入、删除、查找最大(最小)元素等操作的时间复杂度均为 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)。
总之,二叉搜索树和二叉堆在不同场景下各有优劣,需要结合具体需求进行选择。