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. termios.h(FreeBSD 12.0)

    一.文件位置 /usr/include/termios.h 二.文件内容 /*- * SPDX-License-Identifier: BSD-3-Clause * * Copyright (c) 1 ...

  2. idea 创建运行web项目时,报错: Can not issue executeUpdate() for SELECTs解决方案

    最近在做一个Web课程设计的时候遇到了如下的问题. java.sql.SQLException: java.lang.RuntimeException: java.sql.SQLException: ...

  3. Linux 常用命令(2)

    wc命令:用于对文件的行数.单词数和字符数进行统计. wc -w file.txt,显示文件中的单词数,wc -l file.txt,显示文件中的行数,wc -m file.txt,显示文件中的字符数 ...

  4. no plugin found for prefix 'tomcat 7' in the current project

    使用maven build编译出错 “no plugin found for prefix 'tomcat 7' in the current project..........” 参照下面方法 ht ...

  5. 深度学习——深度神经网络(DNN)反向传播算法

    深度神经网络(Deep Neural Networks,简称DNN)是深度学习的基础. 回顾监督学习的一般性问题.假设我们有$m$个训练样本$\{(x_1, y_1), (x_2, y_2), …, ...

  6. Javascript - ExtJs - 数据

    数据(ExtJs Data) Ext.data命名空间 有关数据存储.读取的类都定义在Ext.data命名空间中.Ext的gridPanel.combobox的数据源都是来自Ext.data提供的类. ...

  7. Path Sum I && II & III

    Path Sum I Given a binary tree and a sum, determine if the tree has a root-to-leaf path such that ad ...

  8. python的MySQLdb库链接MySQL入门代码

    链接:http://www.runoob.com/python/python-mysql.html

  9. 【windows下进程searchfilterhost.exe分析】

    searchfilterhost.exe [进程信息] 进程文件: searchfilterhost.exe 进程名称: n/a 英文描述: searchfilterhost.exe is a pro ...

  10. shell监控自动备份是否成功(判断文件是否存在)

    作者:邓聪聪 在自动打包生成备份sql文件后,对运行情况做一个监控!  命令前加time,查看命令执行完成所用时间! FILE_DIR=/root/ DATE=$(date +%F) FILE_NAM ...