二叉查找树(BST)
定义:
二叉查找树(Binary Search Tree),又被称为二叉搜索树。设x为二叉查找树中的一个结点,x节点包含关键字key,节点x的key值记为key[x]。如果y是x的左子树中的一个结点,则key[y] <= key[x];如果y是x的右子树的一个结点,则key[y] >= key[x]
特性:
- 1、 左 子树上所有结点的值均 小于或等于 它的根结点的值。
- 2、 右 子树上所有结点的值均 大于或等于 它的根结点的值。
- 3、左、右子树也分别为 二叉排序树 。
- 4、 没有 键值相等的节点(no duplicate nodes)。
二分查找思想: 以查找值为 10 的节点为例
1、查看根节点 9 :
2、由于 10>9, 因此查看右孩子 13:
3、由于 10<13 ,因此查看左孩子 11:
4、由于 10<11 ,因此查看左孩子10,发现10正是要查找的节点:
查找所需的最大次数==二叉查找树的高度!!
二叉查找树的Java实现
-
BSTree是二叉树,它保护了二叉树的根结点mRoot;
-
mRoot是BstNode类型,而BstNode是二叉查找树的结点,它是BSTree的内部类
-
二叉查找树的节点BstNode包含二叉查找树的几个基本信息:
- key – 它是关键字,是用来对二叉查找树的节点进行排序的。
- left – 它指向当前节点的左孩子。
- right – 它指向当前节点的右孩子。
- parent – 它指向当前节点的父结点。
/**
* @Description: 描述
* @Author: llf
* @CreateDate: 2019/12/14 16:03
*
* <T extends Comparable<T>>:类型 T 必须实现 Comparable 接口,并且这个接口的类型是 T。只有这样,T 的实例之间才能相互比较大小。
*
*/
public class BSTree<T extends Comparable<T>> {
/**
* 根节点
*/
private BstNode<T> mRoot;
/**
* 内部类
* @param <T>
*/
public class BstNode<T extends Comparable<T>>{
/**
* 关键字
*/
T key;
/**
* 左孩子
*/
BstNode<T> left;
/**
* 右孩子
*/
BstNode<T> right;
/**
* 父结点
*/
BstNode<T> parent;
public BstNode(T key, BstNode<T> left, BstNode<T> right,BstNode<T> parent){
super();
this.key = key;
this.left = left;
this.right = right;
this.parent = parent;
}
}
}
插入:
先找到待插入的叶子结点,再在叶子结点上判断与key的关系,以判断key值应该插入到什么位置
/**
* 新建结点key,并将其插入到二叉树中
* @param key 插入结点的键值
*/
public void insert(T key){
BstNode<T> z=new BstNode<T>(key, null, null, null);
//如果新建结点失败,则返回
if (z!=null) {
insert(this,z);
}
}
/**
* 新建结点key,并将其插入到二叉树中
* @param bst 二叉树
* @param z 插入的结点
*/
private void insert(BSTree<T> bst, BstNode<T> z) {
int cmp;
BstNode<T> y=null;
BstNode<T> x=bst.mRoot;//x指向该树的根结点
/**
* 查找z的插入位置
* 比较根结点x与新节点z之间的关系
* 这时,y结点指向根结点x,若z小于根结点,则x指向x的左子树;否则指向右子树
* 直到左/右子树为空 【y结点是x结点的父结点】
* 此时,z.parent指向y
* if y=null
* 新节点z就是父结点;
* else
* 比较z和y的大小,
* if z<y
* z插入到y的左孩子的位置
* else
* z插入到y的右孩子的位置
*/
while(x!=null){
y=x;
cmp=z.key.compareTo(x.key);
if (cmp<0) {
x=x.left;
}else {
x=x.right;
}
}
z.parent=y;
if (y==null) {
bst.mRoot=z;
}else {
cmp=z.key.compareTo(y.key);
if (cmp<0) {
y.left=z;
}else {
y.right=z;
}
}
}
/**
* @Description: 二叉查找树测试
* @Author: llf
* @CreateDate: 2019/12/14 16:29
*/
public class BSTreeTest {
private static final int arr[] = {1, 5, 4, 3, 2, 6};
public static void main(String[] args) {
BSTree<Integer> tree = new BSTree<>();
System.out.println("==依次添加:");
for (int i = 0; i < arr.length; i++) {
System.out.print(arr[i]+" ");
tree.insert(arr[i]);
}
}
}
==依次添加:1 5 4 3 2 6
遍历:
- 前序遍历 首先访问根结点然后遍历左子树,最后遍历右子树。在遍历左、右子树时,仍然先访问根结点,然后遍历左子树,最后遍历右子树,如果二叉树为空则返回。
前序遍历==》ABDECF
若二叉树非空,则执行以下操作:
1、访问根节点
2、先序遍历左子树
3、先序遍历右子树
/**
* 前序遍历二叉树
*/
public void preOrder(){
preOrder(mRoot);
}
private void preOrder(BstNode<T> tree){
if (tree!=null) {
System.out.print(tree.key+" ");
preOrder(tree.left);
preOrder(tree.right);
}
}
System.out.println("==前序遍历:");
tree.preOrder();
==前序遍历:1 5 4 3 2 6
中序遍历 中序遍历首先遍历左子树,然后访问根结点,最后遍历右子树
----》中序遍历结果:DBEAFC
若二叉树非空,则执行以下操作:
-
中序遍历左子
-
树访问根节点
-
中序遍历右子树
/**
* 中序遍历二叉树
*/
public void inOrder(){
inOrder(mRoot);
}
private void inOrder(BstNode<T> tree) {
if (tree!=null) {
inOrder(tree.left);
System.out.print(tree.key+" ");
inOrder(tree.right);
}
}
后序遍历 后序遍历首先遍历左子树,然后遍历右子树,最后访问根结点,在遍历左、右子树时,仍然先遍历左子树,然后遍历右子树,最后遍历根结点。
-----》后序遍历结果:DEBFCA
若二叉树非空,则执行以下操作:
1、后序遍历左子树
2、后序遍历右子树
3、访问根节点
/**
* 后序遍历二叉树
*/
public void postOrder(){
postOrder(mRoot);
}
private void postOrder(BstNode<T> tree) {
if (tree!=null) {
postOrder(tree.left);
postOrder(tree.right);
System.out.print(tree.key+" ");
}
}
System.out.println("==后序遍历:");
tree.postOrder();
==后序遍历:
2 3 4 6 5 1
二叉查找树BST——Java实现 https://blog.csdn.net/u014067137/article/details/80336127