BST树(binary search tree)
定义:二叉排序树或者是一棵空树,或者是具有下列性质的二叉树:
(1)若左子树不空,则左子树上所有节点的值均小于它的根节点的值;
(2)若右子树不空,则右子树上所有节点的值均大于它的根节点的值;
(3)左、右子树也分别为二叉搜索树;
(4)没有值相等的节点。
二叉树每层节点个数为2^n ,树高为log2n
关于执行效率:在一棵二叉查找树上,执行查找、插入、删除等操作,的时间复杂度为O(logn)。因为,一棵由n个结点,随机构造的二叉查找树的高度为logn,所以顺理成章,一般操作的执行时间为O(logn)。
二叉树的基本操作:
5、判断一个二叉树是否是BST树,判断一个BST树是否是AVl树
7、把BST树满足[begin,end]区间的值放在集合中、打印出来
代码与解释:
首先定义一个BST树:
class BSTNode<T extends Comparable<T> >{
private T data;
private BSTNode<T> left;
private BSTNode<T> right;
public T getData() {
return data;
}
public void setData(T data) {
this.data = data;
}
public BSTNode getLeft() {
return left;
}
public void setLeft(BSTNode<T> left) {
this.left = left;
}
public BSTNode getRight() {
return right;
}
public void setRight(BSTNode<T> right) {
this.right = right;
}
public BSTNode(T data, BSTNode<T> left, BSTNode<T> right) {
this.data = data;
this.left = left;
this.right = right;
}
}
1、插入操作
插入操作是BST最简单的操作,类似二分法一样。可以使用递归或者非递归实现。
class BSTree<T extends Comparable<T>>{
//指向根节点
private BSTNode<T> root;
public BSTree() {
this.root = null;
}
//非递归实现BST树的插入操作
public void non_insert(T data){
if(root == null){
this.root = new BSTNode<>(data,null,null);
return;
}
//搜索BST树,找到data合适插入位置
BSTNode<T> parent = null;
BSTNode<T> cur = this.root;
while( cur != null){
parent = cur;
if(cur.getData().compareTo(data) < 0){
cur = cur.getRight();
}else if (cur.getData().compareTo(data) > 0){
cur = cur.getLeft();
}else {
return;
}
}
//生成data节点,并把节点写入其父节点相应的地址域
if(parent.getData().compareTo(data) < 0){
parent.setRight(new BSTNode<>(data,null,null));
}else {
parent.setLeft(new BSTNode<>(data,null,null));
}
}
//递归实现BST树插入操作
public void n_insert(T data){
root = insert(root, data);
}
private BSTNode insert(BSTNode root, T data) {
if(root == null){
return new BSTNode(data, null, null);
}
if(root.getData().compareTo(data) > 0){
root.setLeft(insert(root.getLeft(), data));
} else if(root.getData().compareTo(data) < 0){
root.setRight(insert(root.getRight(), data));
}
return root;
}
}
2、删除操作
BST节点的删除 :
节点类型分为3种情况:
1、待删除结点有 两个孩子节点:
找删除结点的前驱节点 或者 后继节点,用前驱节点或后继节点的值把当前节点的值覆掉,然后直接删除掉前驱节点或后继节点。
前驱节点:待删节点的左子树中值最大的。
后继节点:待删节点的右子树中值最小的
2、有一个孩子节点:直接删除掉,然后把孩子接上就行
3、没有孩子节点:直接删除。
比如:删除36节点
1、找到前驱节点,并替换
2、删除前驱节点
删除完成。
//非递归删除节点
public void non_remove(T data){
//1. 先搜索值为data的待删除节点
if(this.root == null){
return;
}
BSTNode<T> parent = null; // parent = root
BSTNode<T> cur = this.root;
while(cur != null){
if(cur.getData().compareTo(data) > 0){
parent = cur;
cur = cur.getLeft();
} else if(cur.getData().compareTo(data) < 0){
parent = cur;
cur = cur.getRight();
} else {
break;
}
}
// BST中不存在值为data的节点
if(cur == null){
return;
}
//2.处理有两个孩子的待删除节点情况
if(cur.getLeft() != null && cur.getRight() != null){
BSTNode<T> old = cur;
parent = cur;
cur = cur.getLeft();
while(cur.getRight() != null){
parent = cur;
cur = cur.getRight();
}
old.setData(cur.getData());
}
//3.删除有一个孩子的或者没有孩子的节点 cur
BSTNode<T> child = cur.getLeft();
if(child == null){
child = cur.getRight();
}
// data parent.getData()
if(parent == null){ // 表示删除的是根节点
this.root = child;
} else {
if(cur == parent.getLeft()){ // 把cur的child写入父节点的左孩子域
parent.setLeft(child);
} else { // 把cur的child写入父节点的右孩子域
parent.setRight(child);
}
}
}
//递归删除节点
public void remove(T data){
root = remove(root, data);
}
private BSTNode remove(BSTNode root, T data) {
if(root == null){
return null;
}
if(root.getData().compareTo(data) > 0){
root.setLeft(remove(root.getLeft(), data));
} else if(root.getData().compareTo(data) < 0){
root.setRight(remove(root.getRight(), data));
} else {
//表示找到值为val的节点了
if(root.getLeft() != null && root.getRight() != null){
//后继节点替换
BSTNode p = root.getRight();
while(p.getLeft() != null){
p = p.getLeft();
}
root.setData(p.getData());
root.setRight(remove(root.getRight(), (T)p.getData()));
} else {
//有一个孩子或者叶子节点
if(root.getLeft() != null){
return root.getLeft();
}
if(root.getRight() != null) {
return root.getRight();
}
return null;
}
}
return root;
}