当前位置: 首页 > 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;
}

码字不易,求关注


http://www.mrgr.cn/news/100198.html

相关文章:

  • 霍格软件测试-JMeter高级性能测试一期
  • 【音视频】AVIO输入模式
  • 蓝桥杯 3. 密码脱落
  • iOS/Android 使用 C++ 跨平台模块时的内存与生命周期管理
  • 施磊老师基于muduo网络库的集群聊天服务器(七)
  • OpenHarmony之电源管理子系统公共事件定义
  • FX10(CYUSB4014)USB3.2(10Gbps)开发笔记分享(1):硬件设计与开发环境搭建
  • CMake ctest
  • 用diffusers库从单文件safetensor加载sdxl模型(离线)
  • 深入解析 Linux 中动静态库的加载机制:从原理到实践
  • 深入解析YOLO v1:实时目标检测的开山之作
  • PCI 总线学习笔记(五)
  • 蜜罐管理和数据收集服务器:Modern Honey Network (MHN)
  • 高效使用DeepSeek对“情境+ 对象 +问题“型课题进行开题!
  • ClickHouse 中`MergeTree` 和 `ReplicatedMergeTree`表引擎区别
  • C++23中if consteval / if not consteval (P1938R3) 详解
  • 图解YOLO(You Only Look Once)目标检测(v1-v5)
  • windows作业job介绍
  • 【音视频】⾳频处理基本概念及⾳频重采样
  • Virtuoso ADE采用Spectre仿真中出现MOS管最小长宽比满足要求依然报错的情况解决方法