目录

一、二叉搜索树的概念

二、二叉搜索树的操作

1、查找

2、插入

3、删除

三、二叉搜索树的实现

四、二叉搜索树的两种模型

1、K模型

2、KV模型

五、二叉搜索树性能分析


一、二叉搜索树的概念

二叉搜索树又称二叉排序树,它是一颗空树或者是具有以下性质的树:

  • 若它的左子树不为空,则左子树上所有节点的值都小于根节点的值
  • 若它的右子树不为空,则右子树上所有节点的值都大于根节点的值
  • 它的左右子树也分别为二叉搜索树

二、二叉搜索树的操作

1、查找

基本思路:

  • 根节点为空,返回false
  • 根节点不为空,比较根节点和要找的值是否相等,相等返回true。
  • 根节点和要找的值不想等时,判断跟节点和要找的值的关系。
  • 如果根节点小于要找到的值,则在右子树找
  • 如果根节点大于要找的值,在左子树找。

2、插入

  • 树为空,直接插入

  • 树不为空,按照二叉搜索树的特点,找到插入的位置,插入节点。

3、删除

首先查找元素是否在二叉搜索树中,如果不存在,则返回, 否则要删除的结点可能分下面四种情况:

  • 要删除的结点无孩子结点:直接删除该节点
  • 要删除的结点只有左孩子结点:删除该结点且使被删除节点的双亲结点指向被删除节点的左孩子结点
  • 要删除的结点只有右孩子结点:删除该结点且使被删除节点的双亲结点指向被删除结点的右孩子结点
  • 要删除的结点有左、右孩子结点:在它的右子树中寻找中序下的第一个结点(关键码最小),用它的值填补到被删除节点中,即找到右子树的最左节点进行替换。要注意的是,有可能删除的节点的孩子节点就是最左节点。

三、二叉搜索树的实现

#pragma once
#include<iostream>template<class k>
struct BSTNode
{k value;struct BSTNode<k>* left;struct BSTNode<k>* right;BSTNode(const k& val):value(val), left(nullptr), right(nullptr){}
};template<class k>
class BSTree
{typedef BSTNode<k> Node;
public:bool Insert(const k& val){//根节点为空格,直接插入if (root == nullptr){root = new Node(val);return true;}//根节点不为空,先找到合适的位置,在插入Node* parent = root;Node* cur = root;while (cur){//如果找到相同节点,则不需要插入if (cur->value == val){return false;}else if (cur->value < val){parent = cur;cur = cur->right;}else{parent = cur;cur = cur->left;}}//找到了,创建节点进行插入Node* tmp = new Node(val);if (parent->value < val){parent->right = tmp;}else{parent->left = tmp;}return true;}const Node* find(const k& val){Node* cur = root;while (cur){if (cur->value == val){return cur;}else if (cur->value < val){cur = cur->right;}else{cur = cur->left;}}return nullptr;}bool Erase(const k& val){//查找Node* parent = nullptr;Node* cur = root;while (cur){if (cur->value > val){//在左子树parent = cur;cur = cur->left;}else if (cur->value < val){//在右子树找parent = cur;cur = cur->right;}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;elseparent->right = cur->left;}}else{//左右子树都不为空,找右树的最小节点Node* minNode = cur->right;Node* minNodeParent = cur;while (minNode->left){minNodeParent = minNode;minNode = minNode->left;}//将要删除的节点和该节点交换cur->value = minNode->value;//删除交换后的节点if (minNodeParent->left == minNode)minNodeParent->left = minNode->right;elseminNodeParent->right = minNode->right;//删除节点delete minNode;}return true;}}return false;}
public:Node* root = nullptr;
};#include "BSTree.h"void print(BSTNode<int>* node)
{if (node == nullptr)return;std::cout << node->value<<" ";print(node->left);print(node->right);
}void test()
{BSTree<int> bt;bt.Insert(5);bt.Insert(2);bt.Insert(6);bt.Insert(8);bt.Insert(1);bt.Insert(6);bt.Insert(8);bt.Insert(8);//中序打印二叉树print(bt.root);if (bt.find(2) != nullptr)std::cout << "找到了" << std::endl;bt.Erase(2);print(bt.root);}int main()
{test();return 0;
}

四、二叉搜索树的两种模型

1、K模型

K模型是指,在二叉搜索树的节点中,只有key值作为关键码。关键码即为搜索到的价值。

  • 例如,将一组数据以二叉搜索树的结构进行存储,需要找某一个数据时直接在二叉搜索树中查找该值是否存在,如果存在则输出。
  • 在这个示例中,二叉搜索树的每一个节点中都只存储了一个数作为key值。

2、KV模型

KV模型是指,每一个关键码key,都有与之对应的值Value,即<Key, Value>的键值对。

  • 例如,英汉语词典中,给定一个英语单词要求输出汉语意思。这里,英语单词就是key,该英语单词对应的汉语就是Value.
  • 在这个二叉搜树中,每个节点需要存两个关键码key和value,即英语单词和对应的中文。
  • 在输入一个英语单词时,只需要根据输入的英语单词在二叉搜索树中进行查找,并输出相应的中文意思。
  • 需要注意的是,在KV模型中,只需要根据key值在二叉树中进行查找。

实现一个KV模型的英译汉词典

#pragma once
#include<iostream>
#include<string>
#include<stack>template<class K,class V>
struct Node
{K key;V value;Node<K, V>* left;Node<K, V>* right;//构造函数,通过指定的key和value值创建节点Node(const K& _key, const V& _val):key(_key), value(_val), left(nullptr), right(nullptr){}
};template<class K,class V>
class BSTreeKV
{typedef Node<K, V> Node;
public://默认构造一个空的,只有当插入节点时才创建root节点//插入一个节点void insert(const K& key, const V& value){Node* newNode = new Node(key, value);//如果根节点为空,直接插入if (root == nullptr)root = newNode;else{//找到一个合适的插入位置,进行插入Node* cur = root;while (cur->left || cur->right){if (cur->key > newNode->key){if (cur->left == nullptr)break;cur = cur->left;}else if (cur->key < newNode->key){if (cur->right == nullptr)break;cur = cur->right;}else {//已经存在该节点, 不重复插入return;}}//判断prev和cur的关系,将newNode插入if (cur->key > newNode->key){cur->left = newNode;}else{cur->right = newNode;}}}//查找void find(const K& k){Node* cur = root;while (cur){if (cur->key > k){cur = cur->left;}else if (cur->key < k){cur = cur->right;}else{std::cout << k << "->"<<cur->value<<std::endl;break;}}if (cur == nullptr){std::cout << "没有找到该节点" << std::endl;}}//删除void erase(const K& k){Node* parent = nullptr;Node* cur = root;while (cur){if (cur->key > k){parent = cur;cur = cur->left;}else if (cur->key < k){parent = cur;cur = cur->right;}else{//找到了要删除的节点//左子树为或者右子树为空,根节点指向cur的;另一个孩子节点if (cur->left == nullptr){if (parent->left == cur){parent->left = cur->right;}elseparent->right = cur->right;}else if (cur->right == nullptr){if (parent->left == cur){parent->left = cur->left;}elseparent->right = cur->left;}//左右子树都不为空,找最左节点进行替换else{Node* tmp = cur;while (tmp->left){parent = tmp;tmp = tmp->left;}//交换cur和tmpcur->key = tmp->key;cur->value = tmp->value;if (tmp->right){parent->left = tmp->right;}elseparent->left = nullptr;delete tmp;}//删除成功std::cout << "删除成功" << std::endl;break;}}if (cur == nullptr){std::cout << "没有找到要删除的节点"<<std::endl;}}//非递归---前序遍历void prevPrint(){std::stack<Node*> st;Node* cur = root;while (cur || !st.empty()){//打印并将左路节点入栈while (cur){st.push(cur);std::cout << "<" << cur->key << "," << cur->value << ">" << " ";cur = cur->left;}//左路节点出栈并将右孩子节点入栈Node* tmp = st.top();st.pop();cur = tmp->right;}std::cout << std::endl;}
private:Node* root = nullptr;
};

五、二叉搜索树性能分析

二叉搜索树中,无论是插入一个节点还是删除一个节点都首先要进行查找。二叉树的查找时间复杂度为树的深度的函数。

最优情况:该二叉搜索树是一个完全二叉树,深度为logN,时间复杂度为O(logN)

最差情况:该二叉树时一个单支树,深度为N,时间复杂度为O(N)

C++---二叉搜索树相关推荐

  1. LeetCode简单题之二叉搜索树的最小绝对差/最小距离

    题目 给你一个二叉搜索树的根节点 root ,返回 树中任意两不同节点值之间的最小差值 . 差值是一个正数,其数值等于两值之差的绝对值. 示例 1: 输入:root = [4,2,6,1,3] 输出: ...

  2. LeetCode简单题之二叉搜索树的范围和

    题目 给定二叉搜索树的根结点 root,返回值位于范围 [low, high] 之间的所有结点的值的和. 示例 1: 输入:root = [10,5,15,3,7,null,18], low = 7, ...

  3. 【剑指Offer】23、二叉搜索树的后序遍历序列

      题目描述:   输入一个整数数组,判断该数组是不是某二叉搜索树的后序遍历的结果.如果是则输出Yes,否则输出No.假设输入的数组的任意两个数字都互不相同.   解题思路:   对于后续遍历序列,序 ...

  4. 消除左递归实验代码_「leetcode」108. 构造二叉搜索树【递归】【迭代】详解!

    构造二叉搜索树,一不小心就平衡了 ❞ 108.将有序数组转换为二叉搜索树 将一个按照升序排列的有序数组,转换为一棵高度平衡二叉搜索树. 本题中,一个高度平衡二叉树是指一个二叉树每个节点 的左右两个子树 ...

  5. 剑指offer:面试题36. 二叉搜索树与双向链表

    题目: 二叉搜索树与双向链表 输入一棵二叉搜索树,将该二叉搜索树转换成一个排序的循环双向链表.要求不能创建任何新的节点,只能调整树中节点指针的指向. 为了让您更好地理解问题,以下面的二叉搜索树为例: ...

  6. 剑指offer:面试题33. 二叉搜索树的后序遍历序列

    题目:二叉搜索树的后序遍历序列 输入一个整数数组,判断该数组是不是某二叉搜索树的后序遍历结果.如果是则返回 true,否则返回 false.假设输入的数组的任意两个数字都互不相同. 参考以下这颗二叉搜 ...

  7. 二叉树:二叉搜索树实现 逆序数问题

    关于逆序数的问题描述如下: 已知数组nums,求新数组count,count[i]代表了在nums[i]右侧且比 nums[i]小的元素个数. 例如: nums = [5, 2, 6, 1], cou ...

  8. 二叉树:二叉搜索树的编码和解码

    二叉搜索树的编码和解码描述: 编码:即将一个二叉搜索树编码,节点数值转换为字符串 解码:即将一个字符串解码,数值转换为对应的二叉搜索树的节点 过程导图如下: 针对性编码实现如下: /*数字转字符串*/ ...

  9. 二叉树:二叉搜索树的创建和插入

    二叉搜索树又名二叉排序树. 大概简略的思维导图如下,方便记忆特性 基本二叉搜索树创建过程如下 /*数据结构如下*/ typedef struct tree {int data;struct tree ...

  10. 6-12 二叉搜索树的操作集

    6-12 二叉搜索树的操作集(30 分) 本题要求实现给定二叉搜索树的5种常用操作. 函数接口定义: BinTree Insert( BinTree BST, ElementType X ); Bin ...

最新文章

  1. python中math库_Python库详解之math库
  2. 南京大学人工智能本科专业教育培养体系
  3. YII用户注冊和用户登录(五)之进行session和cookie分析 ,并在前后区分session和cookie...
  4. 爬取许嵩新歌《雨幕》弹幕,告诉你什么才是真正的创作!
  5. javascript的内置对象以及BOM(定时器,location)
  6. sun.misc.Unsafe苦难告诉我们什么
  7. grid - 隐式命名网格线名称
  8. 基于asp.net的Web开发架构探索(转)
  9. 闲鱼靠什么支撑起万亿的交易规模?
  10. getFields和getDeclaredFields
  11. 黑马程序员-Java学习笔记之抽象类,接口,多态和内部类
  12. 常用screen参数
  13. Jest 自动化测试框架 笔记
  14. 职业投资策略(转贴)
  15. flushia系统_IA 系统和应用 第七章 环境组态.pdf
  16. win10蓝牙android上网,Win10系统如何共享安卓手机蓝牙上网(非热点)
  17. linux 使用samba共享文件夹
  18. 用JAVA awt实现Image Asset Studio生成圆形或圆角矩形图片功能
  19. 优化距离计算函数的matlab实现
  20. 毕业三年,一事无成,被迫回老家,一个决定改变一生。

热门文章

  1. 一个完整的网络访问过程的分析(从计算机网络的角度)
  2. Excel通过VBA打印信封
  3. BLheli-F330电调相关实验方案
  4. 036 林清玄:有品质的生活,从来都不是钱决定的
  5. java 游戏开发项目教程 赛尔号
  6. CodeForces 104B-Testing Pants for Sadness(思维题)
  7. 三星的新Galaxy Note 20阵容比手机更轻薄
  8. 如何实现文档数字签名?文档签名有什么好处?
  9. golang 面试题(十三)interface内部结构和nil详解
  10. 公共关系与人际交往能力答案