简介
二叉搜索树是一种特殊的二叉树
在我看来感觉象将二分查找图像化.
满足以下条件 :
- 每个节点最多有两个孩子
- 每个节点的值,都大于左孩子,而小于右孩子
特点
- 首先在每一层上二叉树的节点最大为
2^(i-1)
(i为层数). - 二叉树的深度为
k = [log2(n)]+1
(n为总的节点个数).
代码
BSTNode
值得注意的是 :
- get和set方法直接生成就好
- 定义左右孩子时将泛型写上
class BSTNode<T extends Comparable<T>> {
// 节点的数据域
private T data;
// 节点的左孩子域
private BSTNode<T> left;
// 节点的右孩子域
private BSTNode<T> right;
public BSTNode(T data, BSTNode<T> left, BSTNode<T> right) {
this.data = data;
this.left = left;
this.right = 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;
}
}
BSTree初始化 :
类型擦除
class BSTree<T extends Comparable<T>> {
// 构建指向树根的节点
private BSTNode<T> root;
/**
* BST树的初始化
*/
public BSTree() {
this.root = null;
}
}
insert() : 构建二叉搜索树
此处添加了parent节点保存在
cur为null
时的父亲节点 ,用于最后添加新节点
public void non_insert(T data) {
if (root == null) { // 添加根节点
root = new BSTNode<>(data, null, null);
}
// 搜索BST树,找到data合适的插入位置
BSTNode<T> parent = null;
BSTNode<T> cur = this.root;
while(cur != null){
parent = cur;
if(cur.getData().compareTo(data) < 0){ // cur.data < data ,找其右节点
cur = cur.getRight();
} else if(cur.getData().compareTo(data) > 0){ // cur.data > data ,找其左节点
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));
}
}
remove():非递归的删除
操作次序
- 先找到要删除的元素的位置,此处和insert一样,用parent节点作为最后删除的依赖
- 然后根据该元素节点的情况再进行对应的操作
该元素节点可能出现的情况
1.含有两个节点的情况(1.左右孩子)
eg : 此时删除data = 43节点时,想保证二叉树的顺序性,必须满足大于23 并且小于52的data值的节点
主要思想:找到删除节点的前驱节点或者后继节点,用前驱节点或者后继节点的值把当前的节点的值把当前的节点的值覆盖,直接将前驱节点或者后继节点删除即可
前驱节点: 待删节点左子树中值最大的节点
后继节点: 待删节点右子树中值最小的节点
2.节点有一个孩子
3.节点没有孩子
2,3可看为同一种情况,把删除节点的孩子,写入父节点相应的地址域中
/**
* BST树的非递归删除操作
* @param data
*/
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);
}
}
}
遍历
/**
* 前序遍历递归实现
* @param root
*/
private void preOrder(BSTNode<T> root) {
if(root != null){
System.out.print(root.getData() + " "); // V
preOrder(root.getLeft()); // L
preOrder(root.getRight()); // R
}
}