二叉树搜索树的应用

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


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. 二叉树创建字符串
    (本章完)
相关文章
|
监控 物联网 视频直播
流量卡类型及其适用场景
不同流量卡的使用场景可以根据其特点、套餐内容、价格以及用户的具体需求来划分。以下是一些常见的流量卡类型及其适用场景:
|
Ubuntu Oracle 关系型数据库
ubuntu18.04.6的安装教程
VirtualBox正在积极开发,发布频繁,功能、支持的客户操作系统和运行平台越来越多。VirtualBox是一个由专门公司支持的社区项目:鼓励每个人都做出贡献,同时Oracle确保产品始终符合专业质量标准。
533 1
|
11月前
|
存储 关系型数据库 分布式数据库
PolarDB 开源基础教程系列 1 架构解读
PolarDB 是阿里云研发的云原生分布式数据库,基于 PostgreSQL 开源版本,旨在解决传统数据库在大规模数据和高并发场景下的性能和扩展性问题。其主要特点包括: 1. **存储计算分离架构**:通过将计算与存储分离,实现极致弹性、共享一份数据以降低成本、透明读写分离。 2. **HTAP 架构**:支持混合事务处理和分析处理(HTAP),能够在同一系统中高效执行 OLTP 和 OLAP 查询。 3. **优化的日志复制机制**:采用只复制元数据的方式减少网络传输量,优化页面回放和 DDL 锁回放过程。 4. **并行查询与索引创建**:引入 MPP 分布式执行引擎。
540 8
|
人工智能 Cloud Native Java
云应用开发平台CAP深度测评
云应用开发平台CAP是阿里云提供的一站式应用开发及管理平台,支持快速构建和迭代云上应用。通过丰富的Serverless + AI应用模板和先进的开发者工具,CAP帮助企业快速实现业务场景,提高研发、部署、运维效率。用户可免费试用,申请试用资格后,即可快速部署和使用。
|
存储 开发工具 git
git工具使用教程全讲解
本文介绍了版本控制的概念及其重要性,详细对比了多种版本控制工具,如VSS、CVS、SVN和Git,重点讲解了Git的基本使用方法、工作原理及与SVN的区别。此外,文章还介绍了GitHub、GitLab和Gitee等流行的代码托管平台,以及如何在这些平台上注册账号、创建和管理仓库。最后,文章还提供了如何在IntelliJ IDEA中配置和使用Git的具体步骤。
472 1
|
安全 网络安全 网络虚拟化
Cisco-交换机划分Vlan
Cisco-交换机划分Vlan
244 2
|
机器学习/深度学习 资源调度 自动驾驶
OFDM:赋能5G通信的基石
OFDM:赋能5G通信的基石
1224 3
|
机器学习/深度学习 分布式计算 供应链
Hadoop在特定行业中的应用实例
【8月更文第28天】Hadoop是一个强大的分布式计算框架,能够处理大规模数据集。由于其高可扩展性和成本效益,Hadoop被广泛应用于多个行业中,如金融、医疗保健和零售等。本文将探讨Hadoop在这些行业的具体应用场景和一些成功案例。
584 0
|
机器学习/深度学习 监控 算法
利用深度学习技术实现人脸识别系统
人脸识别技术在当今社会得到了广泛应用,其中深度学习算法的发展为人脸识别系统的性能提升提供了强大支持。本文将介绍如何利用深度学习技术构建一个高效的人脸识别系统,包括数据准备、模型选择、训练过程和系统部署等方面的内容。
|
SQL 数据库
常用SQL查询方法与实例
常用SQL查询方法与实例
547 0