文章目录

  • 1.二叉查找树概念
  • 2.二叉查找树操作
    • 2.1 查找
    • 2.2 插入
    • 2.3 删除
    • 2.4 其他
  • 3. 支持重复数据的二叉查找树
  • 4 有散列表了,还需要二叉查找树?
  • 5 代码实现

1.二叉查找树概念

二叉查找树要求,在树中的任意一个节点,其左子树中的每个节点的值,都要小于这个节点的值,而右子树节点的值都大于这个节点的值。

2.二叉查找树操作

2.1 查找

2.2 插入

2.3 删除

2.4 其他

  • 支持快速地查找最大节点和最小节点、前驱节点和后继节点。
  • 中序遍历二又查找树,可以输出有序的数据序列,时间复杂度是 O(n) ,非常高效。因此,二叉查找树也叫作二叉排序树。

3. 支持重复数据的二叉查找树

  • 通过链表和支持动态扩容的数组等数据结构,把值相同的数据都存储在同一个节点上。
  • 每个节点仍然只存储一个数据。在查找插入位置的过程中,如果碰到一个节点的值,与要插入数据的值相同,我们就将这个要插入的数据放到这个节点的右子树,也就是说,把这个新插入的数据当作大于这个节点的值来处理。

  • 在二叉查找树中,查找、插入、删除等很多操作的时间复杂度都跟树的高度成正比。两个极端情况的时间复杂度分别是 O(n) 和 O(logn) ,分别对应二叉树退化成链表的情况和完全二叉树。
  • 为了避免时间复杂度的退化,针对二又查找树,我们又设计了一种更加复杂的树,平衡二叉查找树,时间复杂度可以做到稳定的 O(logn)

4 有散列表了,还需要二叉查找树?

  • 散列表时间复杂度可以做到常量级的O(1), 而二叉查找树在比较平衡的情况下, 时间复杂度才是 O(logn), 相对散列表,好像并没有什么优势,那我们为什么还要用二叉查找树呢?
    几个原因:
  • 第一, 散列表中的数据是无序存储的, 如果要输出有序的数据,需要先进行排序.而对于二叉查找树来说,我们只需要中序遍历,就可以在O(n)的时间复杂度内,输出有序的数据序列.
  • 第二, 散列表扩容耗时很多,而且当遇到散列冲突时,性能不稳定,尽管二叉查找树的性能不稳定,但是在工程中,我们最常用的平衡二叉查找树的性能非常稳定,时间复杂度稳定在O(logn).
  • 第三, 尽管散列表的查找等操作的时间复杂度是常量级的,但因为哈希冲突的存在,这个常量不一定比 logn 小,所以实际的查找速度可能不一定比 O(logn) 快. 加上哈希函数的耗时,也不一定就比平衡二又查找树的效率高.
  • 第四, 散列表的构造比二又查找树要复杂,需要考虑的东西很多. 比如散列函数的设计、冲突解决办法、扩容、缩容等.平衡二又查找树只需要考虑平衡性这一个问题,而且这个问题的解决方案比较成熟、固定.
  • 最后,为了避免过多的散列冲突,散列表装载因子不能太大,特别是基于开放寻址法解决冲突的散列表,不然会浪费一定的存储空间.
  • 综合这几点, 平衡二又查找树在某些方面还是优于散列表的, 所以,这两者的存在并不冲突. 我们在实际的开发过程中,需要结合具体的需求来选择使用哪一个.

5 代码实现

/*** @description: 二叉查找树* @author: michael ming* @date: 2019/5/16 23:48* @modified by: */
#include <iostream>
#include <random>
#include <time.h>
using namespace std;
template <class T>
class BSTNode
{public:T data;BSTNode<T> *left, *right;BSTNode():left(NULL), right(NULL){}BSTNode(const T& d, BSTNode<T> *l = NULL, BSTNode<T> *r = NULL){data = d;   left = l;   right = r;}
};
template <class T>
class BST
{private:BSTNode<T>* root;int nodeLen;
public:BST():root(NULL){}~BST(){clear(root);root = NULL;}void clear(BSTNode<T>* nodeP){if(nodeP == NULL)return;if (nodeP == NULL)return;clear(nodeP->left);clear(nodeP->right);delete nodeP;}BSTNode<T>* get_root() const {  return root;    }bool isEmpty() const {  return root == NULL;    }T* search(const T& d) const{return search(d, root);}T* search(const T& d, BSTNode<T>* p) const{while(p != NULL){if(d == p->data)return &(p->data);else if(d < p->data)p = p->left;elsep = p->right;}return 0;}T* get_max_data(){if(root == NULL)return NULL;BSTNode<T>* temp = root;while(temp->right != NULL)temp = temp->right;return &temp->data;}T* get_min_data(){if(root == NULL)return NULL;BSTNode<T>* temp = root;while(temp->left != NULL)temp = temp->left;return &temp->data;}void insert(const T& d){BSTNode<T> *p = root, *prev = NULL;while(p != NULL){prev = p;if(d < p->data)p = p->left;elsep = p->right;}if(root == NULL)root = new BSTNode<T>(d);else if(d < prev->data)prev->left = new BSTNode<T>(d);elseprev->right = new BSTNode<T>(d);}void del(T d){if(root == NULL)return;BSTNode<T> *p = root, *pfather = NULL;while(p != NULL && p->data != d){pfather = p;if(d > p->data)p = p->right;elsep = p->left;}if(p == NULL)   //没找到dreturn;if(p->left != NULL && p->right != NULL)//要删除的节点有2个子节点{BSTNode<T> *minP = p->right, *minPFather = p;//找到右子树最小的跟要删的交换while(minP->left != NULL)   //右子树最小的肯定在左节点{minPFather = minP;minP = minP->left;}p->data = minP->data;   //把右子树最小的数付给要删除的节点datap = minP;   //minP付给p,删除ppfather = minPFather;}//要删除的是叶节点或者只有1个节点BSTNode<T>* child;if(p->left != NULL)child = p->left;else if(p->right != NULL)child = p->right;elsechild = NULL;if(pfather == NULL)//p是根节点root = child;else if(p == pfather->left)pfather->left = child;elsepfather->right = child;delete p;p = NULL;}int get_height(BSTNode<T>* nodep)  //递归法, 求左右子树高度,较大的+1{if(nodep == NULL)return 0;int leftheight = get_height(nodep->left);int rightheight = get_height(nodep->right);return max(leftheight, rightheight) + 1;}void inOrderPrint(BSTNode<T>* nodep)    //二叉查找树用中序打印,是有序的{if (nodep == NULL)return;inOrderPrint(nodep->left);cout << nodep->data << " ";inOrderPrint(nodep->right);}
};int main()
{BST<int> intBST;srand(time(0));for(int i = 0; i < 6; ++i){intBST.insert(rand());}intBST.insert(7);if(intBST.search(7))cout << *(intBST.search(7)) << endl;cout << "BST height: " << intBST.get_height(intBST.get_root()) << endl;intBST.inOrderPrint(intBST.get_root());cout << "max : " << *(intBST.get_max_data()) << ", min : " << *(intBST.get_min_data()) << endl;intBST.del(7);intBST.inOrderPrint(intBST.get_root());return 0;
}

数据结构--二叉查找树 Binary Search Tree相关推荐

  1. 学习数据结构 二叉查找树(binary search tree)

    2019独角兽企业重金招聘Python工程师标准>>> 为学习 LLVM 的 ImmutableSet,其底层的实现选择为 AVL 树(平衡二叉搜索树),我不很熟悉该树,虽然大致知道 ...

  2. 二叉查找树(binary search tree)详解

    二叉查找树(Binary Search Tree),也称二叉排序树(binary sorted tree),是指一棵空树或者具有下列性质的二叉树: 若任意节点的左子树不空,则左子树上所有结点的值均小于 ...

  3. 数据结构-BST(Binary Search Tree)

    /****************************************** 数据结构: BST(Binary Search Tree),二叉查找树;性质: 若结点的左子树不空,则左子树上所 ...

  4. java数组查找文本_基于数组的二叉查找树 Binary Search Tree (Java实现)

    二叉查找树 二叉查找树是一种支持动态查询的数据结构,所谓动态查寻结构:即在当数据集合内容发生改变时,集合内数据的排列组合不用重新构建.这样的数据结构在查询时需要不断变动的场景中是非常高效的,二叉查找树 ...

  5. 二叉排序树(Binary Sort Tree) 又称为二叉查找树(Binary Search Tree) - (代码、分析)

    目录: 代码: 分析: 代码: BSTree.h #ifndef _BSTREE_H_ #define _BSTREE_H_typedef void BSTree;//定义二叉树类型 typedef ...

  6. binary search tree python_二叉查找树(binary search tree)——python实现

    二叉查找树(binary search tree) 顾名思义二叉查找树中每个节点至多有两个子节点,并且还对存储于每个节点中的关键字值有个小小的要求, 即只要这个节点有左节点或右节点,那么其关键字值总的 ...

  7. 二叉搜索树(Binary Search Tree)(Java实现)

    文章目录 1.二叉搜索树 1.1. 基本概念 1.2.树的节点(BinaryNode) 1.3.构造器和成员变量 1.3.公共方法(public method) 1.4.比较函数 1.5.contai ...

  8. 数据结构与算法(C++)– 二叉查找树(Binary Search Tree )

    数据结构与算法(C++)– 二叉查找树(Binary Search Tree ) 1.二叉查找树(BST) 定义: 假设二叉树的节点都是不同的数,对于树点的任一节点,它的左子树都小于它,它的右子树都大 ...

  9. BST(Binary Search Tree 二叉查找树模版)

    /****************************************** 数据结构: BST(Binary Search Tree),二叉查找树;性质: 若结点的左子树不空,则左子树上所 ...

最新文章

  1. LeetCode简单题之二叉搜索树的范围和
  2. openssl1.1.0 支持php,openssl升级到1.0.21以支持nginx http2 ssl
  3. 44)PHP,多个数据库查询(我没试)
  4. 英语采访问题之:你每天上班的动机是什么?
  5. MAC下安装xgboost
  6. Python学习笔记(六)—几个标准类型内建函数
  7. 图解动软代码生成器使用(C#快捷生成代码)
  8. matlab求解非线性方程数值解,[转载]MATLAB求解非线性方程(转)
  9. 根据用户IP精确定位推送消息
  10. 从新手到老手,数位板的选购攻略
  11. android api 和版本对应表汇总
  12. BUUCTF reverse1-10 WP
  13. 如何从零开始学习软件测试
  14. 测试-嵌入式图床外链
  15. UVA 1646 Edge Case
  16. Python 数字转中文大写
  17. C51 Proteus仿真板
  18. 苹果电脑Finder快捷键汇总
  19. Altium Designer文件关联
  20. 压缩 Excel 文件中的图片

热门文章

  1. 如何手工抓取dump文件及分析
  2. 上传SVN丢失.a文件的问题
  3. php_flag .htaccess,Apache服务器中.htaccess文件的实用配置示例集锦
  4. c#利用定时器自动备份数据库(mysql)
  5. linux驱动简单介绍
  6. centos安装python3.5和pip
  7. 两个队列+k叉哈夫曼树 HDU 5884
  8. [Ubuntu]Apt-get命令参数详解
  9. #define va_arg(AP, TYPE)
  10. c/c++ 前置声明 -- typedef问题