📜  python中的bst(1)

📅  最后修改于: 2023-12-03 14:46:37.534000             🧑  作者: Mango

Python中的BST

二叉搜索树(Binary Search Tree)是一种重要的数据结构,它是以树的形式实现的数据结构,其中每个节点都包含一个关键值和两个子节点。BST的特点是,对于树上的任何节点,其左子树中的值小于该节点的值,而其右子树中的值大于该节点的值。这种排序方式使得BST易于搜索和排序。

Python提供了多种实现BST的方式,下面我们将介绍其中几种常见的实现方式。

1. 使用Python内置模块bisect

bisect模块提供了对已排序的序列执行二分查找和插入操作的支持。我们可以使用它来实现一个简单的BST。下面是一个示例代码片段:

import bisect

class Node:
    def __init__(self, value):
        self.value = value
        self.left = None
        self.right = None

    def insert(self, value):
        if value < self.value:
            if self.left is None:
                self.left = Node(value)
            else:
                self.left.insert(value)
        elif value > self.value:
            if self.right is None:
                self.right = Node(value)
            else:
                self.right.insert(value)

    def inorder_traversal(self):
        if self.left:
            for node in self.left.inorder_traversal():
                yield node

        yield self

        if self.right:
            for node in self.right.inorder_traversal():
                yield node

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

    def insert(self, value):
        if self.root is None:
            self.root = Node(value)
        else:
            self.root.insert(value)

    def inorder_traversal(self):
        if self.root:
            return self.root.inorder_traversal()
        else:
            return iter([])

# 示例用法
bst = BST()
bst.insert(5)
bst.insert(3)
bst.insert(7)
bst.insert(1)
bst.insert(4)
bst.insert(6)
bst.insert(8)
for node in bst.inorder_traversal():
    print(node.value)

说明:

  • Node类表示BST的一个节点,包括节点值value,以及左、右子节点leftright
  • BST类包含一个根节点root,并提供插入操作insert和中序遍历操作inorder_traversal
  • insert方法首先判断是否有根节点,如果没有则将该值作为根节点;否则递归调用Node类的insert方法
  • inorder_traversal方法使用生成器实现中序遍历,并返回一个生成器对象。如果根节点为空,则返回一个空的迭代器
  • 示例用法中将一组值(5, 3, 7, 1, 4, 6, 8)插入到BST中,并对BST执行中序遍历

优点:

  • 简单易懂,使用起来方便快捷

缺点:

  • 插入和遍历操作的时间复杂度为O(nlogn),不如其他实现方式快
2. 使用Python内置模块heapq

heapq模块提供了基于堆(heap)操作的支持,它可以用于实现一个简单的BST。下面是一个示例代码片段:

import heapq

class Node:
    def __init__(self, value):
        self.value = value
        self.parent = None
        self.left = None
        self.right = None

    def __lt__(self, other):
        return self.value < other.value

    def __eq__(self, other):
        return self.value == other.value

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

    def insert(self, value):
        node = Node(value)
        heapq.heappush(self.heap, node)

        while len(self.heap) > 1:
            n1, n2 = heapq.heappop(self.heap), heapq.heappop(self.heap)
            parent = Node(n1.value + n2.value)
            parent.left, parent.right = n1, n2
            n1.parent, n2.parent = parent, parent
            heapq.heappush(self.heap, parent)

    def inorder_traversal(self):
        if self.heap:
            return self.heap[0].inorder_traversal()
        else:
            return iter([])

    def __len__(self):
        return len(self.heap)

class HuffmanNode(Node):
    def __init__(self, value, char=None):
        super().__init__(value)
        self.char = char

    def __repr__(self):
        return f"HuffmanNode(value={self.value}, char='{self.char}')"

    def inorder_traversal(self):
        if self.left:
            for node in self.left.inorder_traversal():
                yield node

        yield self

        if self.right:
            for node in self.right.inorder_traversal():
                yield node

# 示例用法
bst = BST()
text = "hello world"
freq = {char: text.count(char) for char in set(text)}
for char, f in freq.items():
    node = HuffmanNode(f, char)
    bst.insert(node)
for node in bst.inorder_traversal():
    if node.char is not None:
        print(f"{node.char} => {node.value}")

说明:

  • Node类表示BST的一个节点,包括节点值value,以及父、左、右子节点parentleftright
  • BST类包含一个堆heap,并提供插入操作insert和中序遍历操作inorder_traversal
  • __lt____eq__方法是用于堆排序的比较方法,表示一个节点小于(或等于)另一个节点
  • 插入操作是基于哈夫曼树实现的,每次插入一个节点时都要同时将最小的两个节点合并为一个新节点,并将新节点插入堆中
  • inorder_traversal方法使用生成器实现中序遍历,并返回一个生成器对象。如果堆为空,则返回一个空的迭代器

优点:

  • 插入和遍历操作的时间复杂度为O(nlogn),比较高效
  • 可以用于基于哈夫曼编码的压缩算法实现

缺点:

  • 实现比较复杂,需要理解堆排序和哈夫曼树的基本原理
3. 使用Python内置模块dataclasses

dataclasses模块提供了数据类(data class)的支持,在Python3.7及以上版本中可以使用。我们可以使用数据类来实现一个简单的BST。下面是一个示例代码片段:

from dataclasses import dataclass

@dataclass
class Node:
    value: int
    left: "Node" = None
    right: "Node" = None

    def insert(self, value):
        if value < self.value:
            if self.left is None:
                self.left = Node(value)
            else:
                self.left.insert(value)
        elif value > self.value:
            if self.right is None:
                self.right = Node(value)
            else:
                self.right.insert(value)

    def inorder_traversal(self):
        if self.left:
            for node in self.left.inorder_traversal():
                yield node

        yield self

        if self.right:
            for node in self.right.inorder_traversal():
                yield node

@dataclass
class BST:
    root: Node = None

    def insert(self, value):
        if self.root is None:
            self.root = Node(value)
        else:
            self.root.insert(value)

    def inorder_traversal(self):
        if self.root:
            return self.root.inorder_traversal()
        else:
            return iter([])

# 示例用法
bst = BST()
bst.insert(5)
bst.insert(3)
bst.insert(7)
bst.insert(1)
bst.insert(4)
bst.insert(6)
bst.insert(8)
for node in bst.inorder_traversal():
    print(node.value)

说明:

  • NodeBST类上使用了@dataclass装饰器,该装饰器自动为类生成__init____repr__方法
  • Node类表示BST的一个节点,包括节点值value,以及左、右子节点leftright
  • BST类包含一个根节点root,并提供插入操作insert和中序遍历操作inorder_traversal
  • 插入操作使用递归实现,和之前的示例代码相同
  • inorder_traversal方法使用生成器实现中序遍历,并返回一个生成器对象。如果根节点为空,则返回一个空的迭代器

优点:

  • 简单易懂,代码量比较少
  • 可以省略__init____repr__方法的实现,使得代码更加简洁

缺点:

  • 用于处理复杂的BST问题时可能不够灵活