You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何基于属性搜索以随机ID为键的二叉搜索树(BST)?

问题描述

我要实现二叉搜索树(BST)的搜索功能,树的节点用随机生成的数字作为key,节点值是包含多个属性的Item对象。按key搜索BST很简单,能根据key的大小关系左右遍历,但按属性(比如标题)搜索时,似乎只能线性遍历所有节点找匹配项,这好像违背了BST的设计初衷。想知道怎么实现搜索标题为“A Book”的节点,目前没找到可行思路。

现有代码
import random

class Item:
    def __init__(self, title, category, language, authors, year_published):
        self.title = title
        self.category = category
        self.language = language
        self.authors = authors
        self.year_published = year_published
        self.id = random.randint(100000, 999999)

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

    def insert(self, item):
        if item.id < self.key:
            if self.left is None:
                self.left = Node(item)
                self.left.value = item
            else:
                self.left.insert(item)
        else:
            if self.right is None:
                self.right = Node(item)
                self.right.value = item
            else:
                self.right.insert(item)

    def find(self, key):
        if key < self.key:
            if self.left is None:
                return None
            else:
                return self.left.find(key)
        elif key > self.key:
            if self.right is None:
                return None
            else:
                return self.right.find(key)
        else:
            return self

def main():
    metamorphosis = Item("Metamorphosis", "Novel", 'English', 'Franz Kafka',1915)
    a_book = Item("A Book", "Biography", 'English', 'Someone',2024)
    journal = Item("A Journal", "Fiction", 'Various', 'Author',2001)

    library_tree = Node(metamorphosis)
    library_tree.insert(a_book)
    library_tree.insert(journal)

    # 想要实现的功能
    library_tree.search_title("A Book")
解决方案

方法1:线性遍历所有节点

这是最直接的实现方式,虽然无法利用BST的有序性,但能快速满足需求。通过递归遍历整棵树的所有节点,逐一检查标题是否匹配。

给Node类添加search_title方法:

def search_title(self, target_title):
    # 检查当前节点
    if self.value.title == target_title:
        return self
    # 递归搜索左子树
    left_result = self.left.search_title(target_title) if self.left else None
    if left_result:
        return left_result
    # 递归搜索右子树
    right_result = self.right.search_title(target_title) if self.right else None
    return right_result

如果需要返回所有匹配标题的节点(比如存在同名书籍),可以修改为收集结果的版本:

def search_title(self, target_title, results=None):
    if results is None:
        results = []
    if self.value.title == target_title:
        results.append(self)
    if self.left:
        self.left.search_title(target_title, results)
    if self.right:
        self.right.search_title(target_title, results)
    return results

方法2:构建辅助索引字典

为了保留BST按key搜索的高效性,同时实现按标题快速查找,可以维护一个额外的字典,将标题映射到对应的Item ID(或直接映射到Node)。这样按标题搜索时,先查字典拿到ID,再用BST的find方法查找,时间复杂度为O(1)+O(log n)。

修改main函数添加索引逻辑:

def main():
    metamorphosis = Item("Metamorphosis", "Novel", 'English', 'Franz Kafka', 1915)
    a_book = Item("A Book", "Biography", 'English', 'Someone', 2024)
    journal = Item("A Journal", "Fiction", 'Various', 'Author', 2001)

    library_tree = Node(metamorphosis)
    # 构建标题到ID的索引字典
    title_to_id = {
        metamorphosis.title: metamorphosis.id,
        a_book.title: a_book.id,
        journal.title: journal.id
    }

    library_tree.insert(a_book)
    library_tree.insert(journal)

    # 按标题搜索的逻辑
    target_title = "A Book"
    if target_title in title_to_id:
        target_node = library_tree.find(title_to_id[target_title])
        print(target_node.value.title)  # 输出"A Book"
    else:
        print("未找到匹配标题的节点")

如果有动态插入新节点的需求,需要在insert方法中同步更新这个索引字典,比如给Node类添加索引参数,或者维护一个全局/类级别的索引。

方法3:构建多属性排序的BST(或其他数据结构)

如果需要频繁按多个属性搜索,可以考虑构建多棵BST,每棵树按不同属性(比如标题、出版年份)作为key排序。但这种方式会增加插入和维护的复杂度,因为每次插入新节点都要在所有BST中插入一次。

也可以改用更适合多维度搜索的数据结构,比如红黑树、哈希表结合BST,但这已经超出了基础BST的范畴。

内容的提问来源于stack exchange,提问作者rgs

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.22 18:52:41