二叉树搜索树

二叉搜索树,同时也称为二叉排序树。它可以为一个空树,或者满足二叉搜索树的性质

  • 如果左子树不为空时,左子树的值小于双亲结点
  • 如果右子树不为空时,右子树的值大于双亲结点
  • 同时,它的左右子树也满足二叉搜索树的性质

    当对二叉搜索树进行中序遍历时,会得到有序序列,所以又被称为二叉排序树
    例如对上图的树进行中序遍历时会产生:【0 1 2 3 4 5 6 7 8 9】

二叉搜索树的操作

  • 树的结构
    按照模板将树的结构给出
template<class T>
struct BSNode
{BSNode(const T&_data = T()) //构造函数,如果用户没有给参数,则调用默认参数:left(nullptr),right(nullptr),data(_data){}BSNode<T>* left;BSNode<T>* right;T data;
};
  • 查找

根据二叉搜索树的性质,左子树的值比根结点的值小,右子树的值比根结点的值大,进行查找。

Node* Find(const T& _data){Node* cur = root;while (cur){if (cur->data < _data)cur = cur->right;else if (cur->data > _data)cur = cur->left;else if (cur->data == _data)return cur;}return nullptr;}
  • 插入 bool Insert(const T&_data)

    i.先判断二叉搜索树是不是空树,如果是空树直接插入
if(root == nullptr)
{root = BSNode(_data);return true;
}

ii.如果树不为空,则判断要把数值插入的位置

Node *cur = root;   //从根结点开始找要插入的位置
Node *parent = nullptr; // 用来保存要插入位置的双亲结点
while(cur)
{parent = cur;    //将双亲结点指向curif (cur->data < _data)  // 用cur 开始往下查找cur = cur->right;else if (cur->data > _data)cur = cur->left;elsereturn false;
}

iii.找到结点,插入操作

cur = new Node(_data);
if (_data < parent->data)  // 用双亲结点来判断,要插入的结点,应给插入到双亲的哪边parent->left = cur;
elseparent->right = cur;
return true;
代码:
bool Insert(const T&_data) //将一个元素插入{if (root == nullptr){root = new Node(_data);return true;}Node* cur = root;Node* parent = nullptr;while (cur){parent = cur;if (cur->data < _data)cur = cur->right;else if (cur->data > _data)cur = cur->left;elsereturn false;}cur = new Node(_data);if (_data < parent->data)parent->left = cur;elseparent->right = cur;return true;}
  • 删除 bool Delete(const T& _data)

i.先判断删除的数值在二叉树中,如果不存在,则返回, 否则要删除的结点可能分下面三种情况
a. 待删除结点只有左孩子
b.待删除结点只有右孩子
c.待删除结点左右孩子都存在

在a类情况和b类情况中需要加一个特判(待删除结点为根结点)

bool Delete(const T& _data){if (root == nullptr) //结点为空{return false;}Node* cur = root;Node* parent = nullptr;while (cur){if (_data == cur->data)break;else if (cur->data < _data){parent = cur;cur = cur->right;}else{parent = cur;cur = cur->left;}}if (cur == nullptr) //未找到return false;//1、只有左孩子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 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->left != nullptr || cur->right != nullptr){//在右子树中找最小值进行替换Node *replace = cur->right;parent = cur;while (replace->left)//在右子树中最左边的结点值最小{parent = replace;replace = replace->left;}cur->data = replace->data; //将要删除的结点与右子树中最小结点的值进行替换if (replace == parent->left){parent->left = replace->right;}else{parent->right = replace->right;}delete replace;replace = nullptr;}return true;}return false;}

完整代码

template<class T>
struct BSNode
{BSNode(const T&_data = T()):left(nullptr),right(nullptr),data(_data){}BSNode<T>* left;BSNode<T>* right;T data;
};
template<class T>
class BSTree
{typedef BSNode<T> Node;
public:BSTree():root(nullptr){}~BSTree(){Destory(root);}BSTree(const BSTree<T>& t){root = copy(t);}Node *copy(BSTree* t){if (t.root == nullptr)return nullptr;Node *temp = new Node;temp->data = t->root;temp->left = copy(t->left);temp->right = copy(t->right);return temp;}bool Insert(const T&_data) //将一个元素插入{if (root == nullptr){root = new Node(_data);return true;}Node* cur = root;Node* parent = nullptr;while (cur){parent = cur;if (cur->data < _data)cur = cur->right;else if (cur->data > _data)cur = cur->left;elsereturn false;}cur = new Node(_data);if (_data < parent->data)parent->left = cur;elseparent->right = cur;return true;}Node* Find(const T& _data){Node* cur = root;while (cur){if (cur->data < _data)cur = cur->right;else if (cur->data > _data)cur = cur->left;else if (cur->data == _data)return cur;}return nullptr;}bool Delete(const T& _data){if (root == nullptr) //结点为空{return false;}Node* cur = root;Node* parent = nullptr;while (cur){if (_data == cur->data)break;else if (cur->data < _data){parent = cur;cur = cur->right;}else{parent = cur;cur = cur->left;}}if (cur == nullptr) //未找到return false;//1、只有左孩子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 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->left != nullptr || cur->right != nullptr){//在右子树中找最小值进行替换Node *replace = cur->right;parent = cur;while (replace->left)//在右子树中最左边的结点值最小{parent = replace;replace = replace->left;}cur->data = replace->data; //将要删除的结点与右子树中最小结点的值进行替换if (replace == parent->left){parent->left = replace->right;}else{parent->right = replace->right;}delete replace;replace = nullptr;}return true;}return false;}private:void Destory(Node*& root){if (root){Destory(root->left);Destory(root->right);root = nullptr;}}Node *root;
};

性能分析:
每次插入或删除结点时都必须进行查找,所以查找的效率决定删除或者插入的效率,最坏情况下,当二叉搜索树为一个单支,其搜索的时间复杂度为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 标准库之 json
  2. HDU 4738 Caocao‘s Bridges(桥、任何位运算一定都要加括号、因为有重边所以用前向星)
  3. 优秀的程序员都在哪里 如何寻找优秀的程序员?
  4. android WebView总结
  5. CSS样式----文字样式
  6. AlertDialog和自定义对话框
  7. 美团产品顾问马占凯:关于育儿,你需要知道的一切
  8. Web 3.0 信息聚合的时代
  9. linux系统 个人使用情况,个人使用Linux操作系统常要做的事
  10. IIS6.0应用程序池回收和工作进程【转:http://www.cnblogs.com/freshman0216/archive/2008/06/02/1212460.html】...
  11. Linux 多线程编程使用pthread_creat()函数条件
  12. AI学习笔记(十四)CNN之图像分割
  13. Vxscan:一款实用综合扫描工具
  14. Vue:返回上一个路由
  15. iOS 网络图片转为UIImage 和微信分享时缩略图片的压缩
  16. POJ 1182 食物链
  17. vue 下载文件的两种方法
  18. BoundsChecker 使用
  19. 「津津乐道播客」#380 津津有味:厨房重地举目皆是刚需,将就不得
  20. MPI中的Bcast, Reduce和Gather使用举例

热门文章

  1. iOS 修改webView字体
  2. java把一个文件的内容复制到另外一个文件
  3. 行走在消失中的五种编程语言
  4. 生成可重集的排列(方法)
  5. 资源字典——程序集之间的资源共享
  6. SQL Server不存在或拒绝访问故障的排除
  7. Tomcat的安装及配置。
  8. 【项目经验】自动回声消除(AEC)原理
  9. windows10下安装tensorflow(gpu版本)
  10. java 守护进程 linux_Java使用appache deamon实现linux守护进程