当前位置: 首页 > news >正文

搜索二叉树-key的搜索模型

二叉搜索树(Binary Search Tree, BST)是一种重要的数据结构,它有两种基本模型:Key模型和Key/Value模型。

一、Key模型

1.基本概念

 Key模型是二叉搜索树中最简单的形式,每个节点只存储一个键值(key),没有额外的数据值(value)。这种模型主要用于判断某个键值是否存在树中。

2.Key模型的特点:
 
- 每个节点只包含一个键值(key)
- 节点的键值必须满足二叉搜索树的性质:左子节点的键值小于父节点,右子节点的键值大于父节点
- 不允许键值重复,即树中所有节点的键值都是唯一的
- 结构简单,适用于只需要判断元素是否存在的场景

3.典型的应用场景
 
- 单词拼写检查:将字典中的所有单词作为键值构建二叉搜索树,可以快速判断一个单词是否正确
- 门禁系统:存储所有授权人员的ID,快速验证某个ID是否有权限
- 数据去重:检查并确保集合中没有重复元素

单词拼写检查示例:

#include <iostream>
#include <string>

// 定义二叉搜索树节点
template<class K>
struct BSTreeNode 
{
    BSTreeNode<K>* _left;   // 左子节点指针
    BSTreeNode<K>* _right;  // 右子节点指针
    K _key;                // 节点存储的键值

    // 构造函数
    BSTreeNode(const K& key)
        : _left(nullptr)
        , _right(nullptr)
        , _key(key)
    {}
};

// 定义二叉搜索树类
template<class K>
class BSTree 
{
    typedef BSTreeNode<K> Node;  // 节点类型别名

private:
    Node* _root = nullptr;      // 根节点指针

public:
    // 构造函数
    BSTree() : _root(nullptr) {}

    // 析构函数
    ~BSTree() 
    {
        Destroy(_root);
    }

    // 插入操作
    bool Insert(const K& key) 
    {
        if (_root == nullptr)
        {
            _root = new Node(key);
            return true;
        }

        Node* parent = nullptr;
        Node* cur = _root;

        while (cur) 
        {
            if (cur->_key < key) 
            {
                parent = cur;
                cur = cur->_right;
            }
            else if (cur->_key > key) 
            {
                parent = cur;
                cur = cur->_left;
            }
            else 
            {
                return false;
            }
        }

        Node* newNode = new Node(key);
        if (parent->_key < key) 
        {
            parent->_right = newNode;
        }
        else {
            parent->_left = newNode;
        }

        return true;
    }

    // 查找操作
    bool Find(const K& key) 
    {
        Node* cur = _root;
        while (cur) 
        {
            if (cur->_key < key) 
            {
                cur = cur->_right;
            }
            else if (cur->_key > key) 
            {
                cur = cur->_left;
            }
            else 
            {
                return true;
            }
        }
        return false;
    }

private:
    // 销毁树的辅助函数
    void Destroy(Node* root) 
    {
        if (root) 
        {
            Destroy(root->_left);
            Destroy(root->_right);
            delete root;
        }
    }
};

int main() 
{
    BSTree<std::string> dictionary;

    // 初始化字典
    dictionary.Insert("apple");
    dictionary.Insert("banana");
    dictionary.Insert("cherry");
    dictionary.Insert("date");

    std::cout << "===== 单词拼写检查系统 =====" << std::endl;
    std::cout << "已加载基础词典(4个单词)\n";
    std::cout << "输入要验证的单词(输入 exit 退出)\n\n";

    std::string input;
    while (true) 
    {
        std::cout << "请输入单词: ";
        std::cin >> input;

        if (input == "exit") 
        {
            std::cout << "\n=== 感谢使用 ===" << std::endl;
            break;
        }

        if (dictionary.Find(input)) 
        {
            std::cout << "[正确] \"" << input << "\" 存在于词典中\n\n";
        }
        else 
        {
            std::cout << "[警告] \"" << input
                << "\" 未在词典中找到,请注意拼写!\n\n";
        }
    }

    return 0;
}

 二、Key/Value模型

1.基本概念

Key/Value模型是二叉搜索树的重要扩展形式,每个节点存储键值对(key-value pair),支持通过key快速查找对应的value。这种模型是构建字典、索引等数据结构的核心基础。

2.核心特性
 
1. 键值对存储:每个节点存储唯一的key及其关联的value
2. 排序依据:仍然基于key维持二叉搜索树性质
3. 动态更新:允许通过相同key更新value
4. 高效查询:保持O(logN)平均查找时间复杂度

3.应用场景

-单词解释

-统计水果出现次数

统计水果出现次数代码示例:

#include <iostream>
#include <string>
#include <algorithm> // 用于大小写转换

// 定义二叉搜索树节点
template<class K, class V>
struct BSTreeNode 
{
    BSTreeNode<K, V>* _left;
    BSTreeNode<K, V>* _right;
    K _key;
    V _value;

    BSTreeNode(const K& key, const V& value)
        : _left(nullptr)
        , _right(nullptr)
        , _key(key)
        , _value(value) {}
};

// 定义二叉搜索树类
template<class K, class V>
class BSTree 
{
    typedef BSTreeNode<K, V> Node;
    Node* _root = nullptr;

    // 递归销毁子树
    void Destroy(Node* root) 
    {
        if (root)
        {
            Destroy(root->_left);
            Destroy(root->_right);
            delete root;
        }
    }

    // 递归中序遍历打印
    void _PrintInOrder(Node* root) const 
    {
        if (root) 
        {
            _PrintInOrder(root->_left);
            std::cout << " " << root->_key << " : " << root->_value << "\n";
            _PrintInOrder(root->_right);
        }
    }

public:
    BSTree() = default;

    ~BSTree() 
    {
        Destroy(_root);
    }

    // 插入或递增计数
    void InsertOrIncrement(const K& key)
    {
        if (!_root) 
        {
            _root = new Node(key, 1);
            return;
        }

        Node* parent = nullptr;
        Node* cur = _root;

        while (cur) 
        {
            if (cur->_key < key)
            {
                parent = cur;
                cur = cur->_right;
            }
            else if (cur->_key > key)
            {
                parent = cur;
                cur = cur->_left;
            }
            else 
            {
                ++cur->_value;
                return;
            }
        }

        Node* newNode = new Node(key, 1);
        if (parent->_key < key) 
        {
            parent->_right = newNode;
        }
        else {
            parent->_left = newNode;
        }
    }

    // 打印统计结果
    void PrintStatistics() const 
    {
        std::cout << "\n===== 水果统计结果 =====\n";
        _PrintInOrder(_root);
        std::cout << "=======================\n";
    }
};

int main() 
{
    BSTree<std::string, int> fruitCounter;

    std::cout << "=== 水果统计系统 ===\n"
        << "输入水果名称进行统计(输入'q'结束)\n"
        << "(自动转换为小写,支持大小写混合输入)\n\n";

    std::string input;
    while (true)
    {
        std::cout << "输入水果名称: ";
        std::cin >> input;

        // 转换为小写
        std::transform(input.begin(), input.end(), input.begin(),
            [](unsigned char c) { return std::tolower(c); });

        if (input == "q") break;

        fruitCounter.InsertOrIncrement(input);
    }

    // 输出统计结果
    fruitCounter.PrintStatistics();

    return 0;
}

单词解释代码示例:

#include <iostream>
#include <string>

// 定义二叉搜索树节点
template<class K, class V>
struct BSTreeNode 
{
    BSTreeNode<K, V>* _left;   // 左子节点指针
    BSTreeNode<K, V>* _right;  // 右子节点指针
    K _key;                  // 键
    V _value;                // 值

    BSTreeNode(const K& key, const V& value)
        : _left(nullptr)
        , _right(nullptr)
        , _key(key)
        , _value(value)
    {}
};

// 定义二叉搜索树类
template<class K, class V>
class BSTree 
{
    typedef BSTreeNode<K, V> Node;  // 节点类型别名

private:
    Node* _root = nullptr;      // 根节点指针

public:
    // 构造函数
    BSTree() : _root(nullptr) {}

    // 析构函数
    ~BSTree() 
    {
        Destroy(_root);
    }

    // 插入操作
    bool Insert(const K& key, const V& value) 
    {
        if (!_root) {  // 空树情况
            _root = new Node(key, value);
            return true;
        }

        Node* parent = nullptr;
        Node* cur = _root;

        while (cur) 
        {  // 查找插入位置
            if (cur->_key < key)
            {
                parent = cur;
                cur = cur->_right;
            }
            else if (cur->_key > key) 
            {
                parent = cur;
                cur = cur->_left;
            }
            else {  // 键值已存在,更新value
                cur->_value = value;
                return false;
            }
        }

        // 创建新节点并插入
        Node* newNode = new Node(key, value);
        if (parent->_key < key) 
        {
            parent->_right = newNode;
        }
        else
        {
            parent->_left = newNode;
        }

        return true;
    }

    // 查找操作
    V* Find(const K& key)
    {
        Node* cur = _root;
        while (cur) 
        {
            if (cur->_key < key) 
            {      // 向右子树查找
                cur = cur->_right;
            }
            else if (cur->_key > key)
            { // 向左子树查找
                cur = cur->_left;
            }
            else 
            {                    // 找到目标节点
                return &cur->_value;
            }
        }
        return nullptr;  // 查找失败
    }

private:
    // 销毁树的辅助函数
    void Destroy(Node* root)
    {
        if (root) 
        {
            Destroy(root->_left);
            Destroy(root->_right);
            delete root;
        }
    }
};


int main() 
{
    BSTree<std::string, std::string> dict;

    // 构建词典
    dict.Insert("apple", "A round fruit with red, green, or yellow skin and a white inside.");
    dict.Insert("banana", "A long curved fruit with yellow skin and soft sweet flesh.");

    // 交互查询
    std::string word;
    while (true) 
    {
        std::cout << "Enter word to lookup (q to quit): ";
        std::cin >> word;
        if (word == "q") break;

        if (auto def = dict.Find(word)) 
        {
            std::cout << "Definition: " << *def << "\n\n";
        }
        else 
        {
            std::cout << "Word not found. Add definition? (y/n) ";
            char choice;
            std::cin >> choice;
            if (choice == 'y') 
            {
                std::string newDef;
                std::cout << "Enter definition: ";
                std::cin.ignore();
                std::getline(std::cin, newDef);
                dict.Insert(word, newDef);
                std::cout << "Added!\n\n";
            }
        }
    }

    return 0;
}

码字不易,求关注

相关文章:

  • nc工具!Netcat:TCP/IP瑞士军刀!全参数详细教程!Kali Linux教程!
  • prometheus通过Endpoints自定义grafana的dashboard模块
  • 时序数据库IoTDB在航空航天领域的解决方案
  • 对Mac文字双击或三击鼠标左键没有任何反应
  • Mac 「brew」快速安装MySQL
  • 河道流量监测,雷达流量计赋能水安全智慧守护
  • 4.26 世界知识产权日|CRMEB与您共筑知识产权保护铠甲
  • 【playwright】 page.wait_for_timeout() 和time.sleep()区别
  • 【华为HCIP | 华为数通工程师】821—多选解析—第十七页
  • Spring 与 ActiveMQ 的深度集成实践(一)
  • 告别进度失控:用燃尽图补上甘特图的监控盲区
  • 第100+39步 ChatGPT学习:R语言实现Xgboost SHAP
  • (三) Trae 调试C++ 基本概念
  • 《AI大模型趣味实战》构建基于Flask和Ollama的AI助手聊天网站:分布式架构与ngrok内网穿透实现
  • 数字人民币杠杆破局预付乱象 XBIT智能合约筑牢资金安全防线
  • 基于Java,SpringBoot,Vue,HTML宠物相亲配对婚恋系统设计
  • 如何实现Android屏幕和音频采集并启动RTSP服务?
  • 【Linux内核设计与实现】第三章——进程管理04
  • 多模态大语言模型(MLLM)- kimi-vl technical report论文阅读
  • UWA DAY 2025 正式启动|十年筑基,驱动游戏未来引擎
  • 剪纸纹样“流动”在水乡,谁不忆江南
  • “五一”假期云南铁路预计发送旅客超330万人次
  • 2025年度人大立法工作计划将公布:研究启动法律清理工作
  • 往事|学者罗继祖王贵忱仅有的一次相见及往来函札
  • 最高法:“盗链”属于信息网络传播行为,构成侵犯著作权罪
  • 秦洪看盘|平淡走势中或将孕育主旋律