1、定义

  对于每个节点X,它的左子树中所有的项的值小于X的值,右子树所有项的值大于X的值。

  

  如图:任意一个节点,都满足定义,其左子树的所有值小于它,右子树的所有值大于它。

2、平均深度

  在大O模型中,二叉查找树的平均深度是O(logN) 。

  证明:查找某个节点x的算法深度,即从根出发找到节点x的路径长。所有查找的平均深度,就是平均内部路径长。

  1. 假设二叉查找树共N个节点,假设左子树有i个节点,则右子树节点数目:N-i-1。
  2. 假设D(N)表示具有N个基点的内部路径长。则N个节点的树的内部路径长:D(N) = D(i) + D(N-i-1) + N -1。(因为i为左子树,N-i-1 为右子树,所以其实际深度应该加上根节点的深度,所有每个节点都应该+1,除根外共有N-1个节点,所以最后要加上N-1)
  3. j根i在求和中没有实际的区别,都是计数而已。

  对D(N)进行i=(0,N-1)求和: (公式用word写出然后截图过来,后续用markdown写好了)

                                                            

  求解公式:得到  

                       

3、代码实现(递归)

  二叉查找树完全代码:

  3.1 )根据查找树的性质,我们存放的值必定是可以比较的,所以我们选择 Comparable 作为eo对象的比较。

  3.2)contains方法:是否含有x

    如果存在节点的值为X,则返回true,否则返回false。

  3.3)findMin和findMax方法:

    二叉查找树的所有节点都有其顺序,这两个方法可以方便的找出最大最小值。

  3.4)insert方法:插入x

    插入操作:按照顺序查找,如果找到x,则直接返回树,否则在合适的地方插入x。

  3.5)remove方法:移除x

    删除操作:如果x是叶子节点,则直接删除,返回树,如果x含有左子树或者右子树,或者含有左右子树,则要做适当的调整树结构。

package chapterFour;

import java.nio.BufferUnderflowException;

/**
* 二叉查找树:
* 左子树的所有项的值均小于根节点,右子树的所有项的值均大于根节点。
*/
public class BinarySearchTree<T extends Comparable<? super T>> { /**
* 节点类
*
* @param <T>
*/
private static class BinaryNode<T> { private T element;
private BinaryNode<T> left;
private BinaryNode<T> right; BinaryNode(T t) {
this(t, null, null);
} public BinaryNode(T t, BinaryNode<T> lt, BinaryNode<T> rt) {
element = t;
left = lt;
right = rt;
}
} // 根节点
private BinaryNode<T> root; /**
* 构造函数
*/
public BinarySearchTree() {
root = null;
} /**
* 清空整颗树
*/
public void makeEmpty() {
root = null;
} /**
* 判断树是否为空:只需要判断根节点是否为空即可。
*
* @return
*/
public Boolean isEmpty() {
return root == null;
} /**
* 是否含有节点x,含有则返回true,没有则返回fales
*
* @param x
* @return
*/
public boolean contains(T x) {
return contains(x, root);
} /**
* 寻找最小值
*
* @return
*/
public T findMin() {
if (isEmpty()) {
throw new BufferUnderflowException();
}
return findMin(root).element;
} /**
* 寻找最大值
*
* @return
*/
public T findMax() {
if (isEmpty()) {
throw new BufferUnderflowException();
}
return findMax(root).element;
} /**
* 插入
*
* @param t
*/
public void insert(T t) {
root = insert(t, root);
} /**
* 删除
*
* @param t
*/
public void remove(T t) {
root = remove(t, root);
} /**
* 打印全部
*/
public void printTree() {
if (isEmpty()) {
System.out.println("Empty tree");
} else {
printTree(root);
}
} /**
* 删除方法:
* 删除一个节点,如果是叶子节点,那么直接删除就好了,但是如果是某个父节点,那么需要重组部分树节点。
*
* @param t
* @param root
* @return
*/
private BinaryNode<T> remove(T t, BinaryNode<T> root) { if (root == null) {
return root;
} int compareResult = t.compareTo(root.element); if (compareResult < 0) {
root.left = remove(t, root.left);
} else if (compareResult > 0) {
root.right = remove(t, root.right);
} else if (root.left != null && root.right != null) {
root.element = findMin(root.right).element;
root.right = remove(root.element, root.right);
} else { root = (root.left != null) ? root.left : root.right;
}
return root; } /**
* 查找树的插入,其实很简单,就一直的递归,然后插入就好了。
*
* @param t
* @param root
* @return
*/
private BinaryNode<T> insert(T t, BinaryNode<T> root) { // 如果树不存在就创建一棵树
if (root == null) {
return new BinaryNode<>(t, null, null);
}
int compareResult = t.compareTo(root.element); // 如果比root小,就插入到root的左边
if (compareResult < 0) {
root.left = insert(t, root.left);
}
// 如果比root大,就插入到root的右边
if (compareResult > 0) {
root.right = insert(t, root.right);
}
// 最后返回树
return root; } /**
* 寻找最大值(方法一,用循环代替递归)
* 我们不使用递归,加判断的递归,可以用while循环
*
* @param root
* @return
*/
private BinaryNode<T> findMax(BinaryNode<T> root) { if (root == null) {
return null;
} while (root.right != null) {
root = root.right;
}
return root;
} /**
* 寻找最小值(方法二,直接使用递归)
* 我们用递归的方法,遍历所有的左子树,直到最后。
*
* @param root
* @return
*/
private BinaryNode<T> findMin(BinaryNode<T> root) {
if (root == null) {
return null;
}
if (root.left == null) {
return root;
} else {
return findMin(root.left);
}
} /**
* 如果T是空集,那么可以就返回false。否则,存在T处的项是X,那么就可以返回ture,否则对树对左子树或右子树进行一次递归。
*
* @param x
* @param root
* @return
*/
private boolean contains(T x, BinaryNode<T> root) { if (root == null) {
return false;
} // 判断x是在左子树还是右子树
int compareResult = x.compareTo(root.element); if (compareResult < 0) {
return contains(x, root.left);
} else {
return contains(x, root.right);
}
} /**
* 按照顺序打印二叉树:中序遍历
*
* @param tb
*/
private void printTree(BinaryNode<T> tb) {
if (tb != null) {
printTree(tb.left);
System.out.println(tb.element);
printTree(tb.right);
}
} }

树·二叉查找树ADT(二叉搜索树/排序树)的更多相关文章

  1. 树-二叉搜索树-AVL树

    树-二叉搜索树-AVL树 树 树的基本概念 节点的度:节点的儿子数 树的度:Max{节点的度} 节点的高度:节点到各叶节点的最大路径长度 树的高度:根节点的高度 节点的深度(层数):根节点到该节点的路 ...

  2. 判断一棵树是否为二叉搜索树(二叉排序树) python

    输入一棵树,判断这棵树是否为二叉搜索树.首先要知道什么是排序二叉树,二叉排序树是这样定义的,二叉排序树或者是一棵空树,或者是具有下列性质的二叉树: (1)若左子树不空,则左子树上所有结点的值均小于它的 ...

  3. 数据结构中的树(二叉树、二叉搜索树、AVL树)

    数据结构动图展示网站 树的概念 树(英语:tree)是一种抽象数据类型(ADT)或是实作这种抽象数据类型的数据结构,用来模拟具有树状结构性质的数据集合.它是由n(n>=1)个有限节点组成一个具有 ...

  4. 树(二叉树 & 二叉搜索树 & 哈夫曼树 & 字典树)

    树:n(n>=0)个节点的有限集.有且只有一个root,子树的个数没有限制但互不相交.结点拥有的子树个数就是该结点的度(Degree).度为0的是叶结点,除根结点和叶结点,其他的是内部结点.结点 ...

  5. 高度平衡的二叉搜索树(AVL树)

    AVL树的基本概念 AVL树是一种高度平衡的(height balanced)二叉搜索树:对每一个结点x,x的左子树与右子树的高度差(平衡因子)至多为1. 有人也许要问:为什么要有AVL树呢?它有什么 ...

  6. 数据结构中常见的树(BST二叉搜索树、AVL平衡二叉树、RBT红黑树、B-树、B+树、B*树)

    树 即二叉搜索树: 1.所有非叶子结点至多拥有两个儿子(Left和Right): 2.所有结点存储一个关键字: 非叶子结点的左指针指向小于其关键字的子树,右指针指向大于其关键字的子树: 如: BST树 ...

  7. HDU 3179 二叉搜索树(树的建立)

    二叉搜索树 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submi ...

  8. 查找树ADT——二叉搜索树

    在以下讨论中,虽然任意复杂的关键字都是允许的,但为了简单起见,假设它们都是整数,并且所有的关键字是互异的. 总概   使二叉树成为二叉查找树的性质是,对于树中的每个节点X,它的左子树中所有关键字值小于 ...

  9. 数据结构中很常见的各种树(BST二叉搜索树、AVL平衡二叉树、RBT红黑树、B-树、B+树、B*树)

    数据结构中常见的树(BST二叉搜索树.AVL平衡二叉树.RBT红黑树.B-树.B+树.B*树) 二叉排序树.平衡树.红黑树 红黑树----第四篇:一步一图一代码,一定要让你真正彻底明白红黑树 --- ...

随机推荐

  1. ps 命令的十个简单用法【转】

    注记 ps 命令有两种不同的语法风格 —— BSD 与 UNIX 两种风格.新手常常对这两种形式产生误解,因此我们有必要在这里作一个简单的说明: ps aux 与 ps -aux 是不同的,例如 -u ...

  2. 【转】Parcelable, Serializable,Cloneable,copyProperties

    Copying ... https://blog.csdn.net/max2005/article/details/78325036 存在着三件事,整理如下 Parcelable, Serializa ...

  3. UE4 位置转换相关函数

    get mouse positionget mouse position scaled by dpiget viewport scaleDeproject Scence to WorldLocal T ...

  4. 配置mongo

    Windows 平台安装 MongoDB MongoDB 下载 MongoDB 提供了可用于 32 位和 64 位系统的预编译二进制包,你可以从MongoDB官网下载安装,MongoDB 预编译二进制 ...

  5. Django REST Framework API Guide 05

    本节大纲 1.Serializer fields 2.Serializer relations Serializer fields 1.serializer 字段定义在fields.py文件内 2.导 ...

  6. Python 12 - Mysql & ORM

    本节内容 1.数据库介绍 2.mysql数据库安装使用 3.mysql数据库基础 4.mysql命令 5.事务 6.索引 7.Python操作mysql 8.ORM sqlalchemy了解 数据库介 ...

  7. 集合-HashSet

    参考博客:https://www.cnblogs.com/runwulingsheng/p/5208762.html https://www.cnblogs.com/ysocean/p/6555373 ...

  8. 围在栅栏中的爱WriteUp(附QWE密码加解密脚本)

    题目的链接:http://www.shiyanbar.com/ctf/1917 1.首先题目给出的是摩尔斯电码: 在下面的网站上解密:https://www.cryptool.org/en/cto-c ...

  9. Centos7.5 VMtools的安装与卸载

    一.安装 1.自带tools:  选择VMware工具栏 => 虚拟机 => 安装VMtools 2.挂载光驱 3.tar -zxvf VMwareTools-10.3.2-9925305 ...

  10. 【转】Python标准模块--importlib

    [转]Python标准模块--importlib 作者:zhbzz2007 出处:http://www.cnblogs.com/zhbzz2007 欢迎转载,也请保留这段声明.谢谢! 1 模块简介 P ...