二叉树搜索树的应用

简介: 二叉树搜索树的应用


1. 二叉树搜索树的应用

  1. K模型:K模型即只有key作为关键码,结构中只需要存储Key即可,关键码即为需要搜索到的值。(确定一个值在不在)
    比如:给一个单词word,判断该单词是否拼写正确,具体方式如下:以词库中所有单词集合中的每个单词作为key,构建一棵二叉搜索树在二叉搜索树中检索该单词是否存在,存在则拼写正确,不存在则拼写错误。
  2. KV模型:每一个关键码key,都有与之对应的值Value,即<Key, Value>的键值对。()
    该种方式在现实生活中非常常见:
    比如英汉词典就是英文与中文的对应关系,通过英文可以快速找到与其对应的中文,英文单词与其对应的中文<word, chinese>就构成一种键值对;
    再比如统计单词次数,统计成功后,给定单词就可快速找到其出现的次数,单词与其出现次数就是<word, count>就构成一种键值对。

改造二叉搜索树为KV结构

#pragma once
#include <iostream>
using namespace std;
namespace KV
{
  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;
  public:
    //插入
    bool Insert(const K& key, const V& value)
    {
      if (_root == nullptr)
      {
        _root = new Node(key,value); 
        return true;
      }
      Node* cur = _root;
      Node* parent = nullptr;
      while (cur)
      {
        parent = cur;
        if (key > cur->_key)
        {
          cur = cur->_right;
        }
        else if (key < cur->_key)
        {
          cur = cur->_left;
        }
        else
        {
          return false;
        }
      }
      cur = new Node(key,value);
      if (key > parent->_key)
      {
        parent->_right = cur;
      }
      if (key < parent->_key)
      {
        parent->_left = cur;
      }
      return true;
    }
    //中序打印
    void InOrder()
    {
      _InOrder(_root);
      cout << endl;
    }
    //查找
    Node * Find(const K& key)
    {
      Node* cur = _root;
      while (cur)
      {
        if (key > cur->_key)
        {
          cur = cur->_right;
        }
        else if (key < cur->_key)
        {
          cur = cur->_left;
        }
        else
        {
          return cur;
        }
      }
      return nullptr;
    }
    //删除
    bool Erase(const K& key)
    {
      Node* cur = _root;
      Node* parent = nullptr;
      while (cur)
      {
        if (key > cur->_key)
        {
          parent = cur;
          cur = cur->_right;
        }
        else if (key < cur->_key)
        {
          parent = cur;
          cur = cur->_left;
        }
        else
        {
          //开删
          if (cur->_left == nullptr)
          {//左为空
            if (cur == _root)
            {
              _root = cur->_right;
            }
            else if (cur == parent->_left)
            {
              parent->_left = cur->_right;
            }
            else
            {
              parent->_right = cur->_right;
            }
          }
          else if (cur->_right == nullptr)
          {//右为空
            if (cur == _root)
            {
              _root = cur->_left;
            }
            else if (cur == parent->_left)
            {
              parent->_left = cur->_left;
            }
            else
            {
              parent->_right = cur->_left;
            }
          }
          else
          {//左右都不为空
            Node* SubLeft = cur->_right;
            Node* _parent = cur;
            while (SubLeft->_left)
            {
              _parent = SubLeft;
              SubLeft = SubLeft->_left;
            }
            swap(cur->_key, SubLeft->_key);
            if (SubLeft == _parent->_left)
            {
              _parent->_left = SubLeft->_right;
            }
            else
            {
              _parent->_right = SubLeft->_right;
            }
          }
          return true;
        }
      }
      return false;
    }
  private:
    void _InOrder(Node* root)
    {
      if (root == nullptr)
      {
        return;
      }
      _InOrder(root->_left);
      cout << root->_key << ":" << root->_value << endl;
      _InOrder(root->_right);
    }
  private:
    Node* _root = nullptr;
  };
}

统计水果出现次数

int main()
{
  string arr[] = { "苹果", "西瓜", "苹果", "西瓜", "苹果", "苹果", 
    "西瓜","苹果", "香蕉", "苹果", "香蕉" };
  KV::BSTree<string, int> CountTree;
  for (auto &e : arr)
  {
    KV::BSTreeNode<string, int>* ret = CountTree.Find(e);
    if (ret == nullptr)
    {
      CountTree.Insert(e,1);
    }
    else
    {
      ret->_value++;
    }
  }
  CountTree.InOrder();
  return 0;
}


输入单词,查找单词对应的中文翻译

int main()
{
  KV::BSTree<string, string> dict;
  dict.Insert("sort", "快排");
  dict.Insert("left", "左边");
  dict.Insert("right", "右边");
  dict.Insert("insert", "插入");
  dict.Insert("key", "键值");
  string str;
  while (cin>>str)
  {
    KV::BSTreeNode<string, string>* ret = dict.Find(str);
    if (ret)
    {
      cout << ret->_value << endl;
    }
    else
    {
      cout << " 无此单词" << endl;
    }
  }
  return 0;
}

2. 二叉搜索树的性能分析

插入和删除操作都必须先查找,查找效率代表了二叉搜索树中各个操作的性能。

对有n个结点的二叉搜索树,若每个元素查找的概率相等,则二叉搜索树平均查找长度是结点在二叉搜索树的深度的函数,即结点越深,则比较次数越多。但对于同一个关键码集合,如果各关键码插入的次序不同,可能得到不同结构的二叉搜索树:

最优情况下,二叉搜索树为完全二叉树(或者接近完全二叉树),其平均比较次数为:l o g 2 N log_2 Nlog2N
最差情况下,二叉搜索树退化为单支树(或者类似单支),其平均比较次数为:N 2 \frac{N}{2}2N

3. 二叉树进阶面试题

这些题目更适合使用C++完成,难度也更大一些

  1. 给定一个二叉树, 找到该树中两个指定节点的最近公共祖先
  2. 二叉树搜索树转换成排序双向链表
  3. 二叉树创建字符串
    (本章完)
相关文章
|
数据安全/隐私保护
Win10 Win7 mstsc远程连接不可用的解决办法
Win10 Win7 mstsc远程连接不可用的解决办法
412 0
|
机器学习/深度学习 算法 测试技术
适合离散值分类的多分类模型——softmax回归
适合离散值分类的多分类模型——softmax回归
适合离散值分类的多分类模型——softmax回归
|
JavaScript 前端开发 Java
for循环、break和continue、二重循环
【10月更文挑战第12天】这段内容介绍了编程中的 `for` 循环,包括基本概念、应用场景以及 `break` 和 `continue` 语句的使用方法。`for` 循环是一种常用的流程控制语句,用于重复执行一段代码。文中通过不同语言的示例说明了如何遍历数组、计算数值和创建矩阵等。此外,还介绍了二重循环的概念及其在处理二维数据结构中的应用。
576 1
|
搜索推荐
搜索树基础:二叉搜索树(详解特性用途,图解实现过程)
搜索树基础:二叉搜索树(详解特性用途,图解实现过程)
|
算法
广度优先遍历(BFS):逐层探索图的算法奥秘
在图论中,广度优先遍历(Breadth-First Search,BFS)是一种图遍历算法,它以一种逐层的方式探索图的节点。通过从起始节点开始,逐层向外扩展,BFS能够帮助我们解决许多与图相关的问题。
676 0
|
算法 测试技术 定位技术
数据结构与算法——DFS(深度优先搜索)
数据结构与算法——DFS(深度优先搜索)
|
机器学习/深度学习 人工智能 运维
智能日志分析:用AI点亮运维的未来
智能日志分析:用AI点亮运维的未来
4795 15
|
存储 数据安全/隐私保护 Windows
7-Zip 的使用技巧
7-Zip 的使用技巧
|
云安全 边缘计算 监控
R9-9950X服务器 超越频率桎梏,企业级稳定性的新标杆!
德迅云安全推出的R9 9950X服务器专为多线程、高负载场景优化,基于AMD Ryzen 9系列的Zen 4架构,采用5nm工艺和CCD/CIOD分离设计,具备16核32线程全大核策略,确保高效能与低功耗。其自适应功耗管理和强化供电设计,保障了在企业级应用中的卓越稳定性和持续性能。搭配德迅卫士主机安全软件,提供实时监控、远程防护及资产清点等全面安全措施,适用于云计算、虚拟化和边缘计算等场景,为企业带来可靠的高性能解决方案。
|
Cloud Native 架构师 测试技术
如何画好一张架构图?(内含知识图谱)
架构图是什么?为什么要画架构图?如何画好架构图?有哪些方法?本文从架构的定义说起,分享了阿里文娱高级技术专家箫逸关于画架构图多年的经验总结,并对抽象这一概念进行了深入地讨论。内容较长,同学们可收藏起来细细阅读。
16123 0
如何画好一张架构图?(内含知识图谱)