二叉搜索树
又称二叉排序树,它或者是一颗空树
1.性质:
若他的左子树不为空,则左子树所有节点的值小于根节点的值
若他的右子树不为空,则有字数上所有节点都小于根节点的值
它的左右子树也分别为二叉搜索树
2.作用:
用来进行搜索
3.二叉搜索树注意事项:
进行中序遍历,可以得到一个有序的序列
树中最左侧节点一定是最小的节点,最右侧节点一定是最大的
4.常见操作
static class BSTnode {
private BSTnode left;
private BSTnode right;
private int value;
BSTnode(int value) {
this.value = value;
}
}
1.插入
boolean put(int key) {
//空树直接插入
if (root == null) {
root = new BSTnode(key);
return true;
}
//找到待插入节点在搜索树中的位置
BSTnode cur=root;
BSTnode parent=null;
while (cur != null) {
parent = cur;
if (key < cur.value) {
cur = cur.left;
} else if (key >cur.value) {
cur = cur.right;
} else {
return false;
}
}
//插入节点
cur = new BSTnode(key);
if (cur.value > parent.value) {
parent.right=cur;
} else {
parent.left=cur;
}
return true;
}
2.删除
1. 待删除节点的左右孩子都不存在
2.待删除节点的左孩子存在
3.待删除节点的右孩子存在
1.2.3可以直接删除,将parent或者root的指向修改
没有双亲
有双亲,双亲的右孩子
有双亲,双亲的左孩子
4. 待删除节点的左右孩子都存在
4.不能直接删除,在其子节点中找到一个替代的节点,将该替代节点的值域交给待删除节点,去删除替代节点
替代节点:待删除节点的左子树中的最大节点 带删除节点的右子树中的最小节点
public void delete(int key){
BSTnode cur=root;
BSTnode parent=null;
//找到待删除节点的位置
while(cur!=null) {
if (cur.value == key) {
break;
} else if (key < cur.value) {
parent=cur;
cur = cur.left;
} else {
parent=cur;
cur = cur.right;
}
}
if(cur.left==null){//cur只有右孩子
if(parent==null){ //双亲不存在 cur是根节点
root=cur.right;
}else {
if (cur == parent.left) {//双亲存在,cur是双亲的左孩子
parent.left = cur.right;
} else { //双亲存在,cur是双亲的右孩子
parent.right = cur.right;
}
}
} else if(cur.right==null){//cur只有左孩子
if(parent==null){ //双亲不存在 cur是根节点
root=cur.left;
}else {
if (cur == parent.left) {//双亲存在,cur是双亲的左孩子
parent.left = cur.left;
} else { //双亲存在,cur是双亲的右孩子
parent.right = cur.left;
}
}
}else{//cur左右孩子都存在
//右子树中最小节点
BSTnode del=cur.right;
parent=cur;
while(null!=del.left){
del=del.left;
}
//替代节点找到
cur.value=del.value;
//删除替代节点
if(del==parent.left){
parent.left=del.right;
}else{
parent.right=del.right;
}
}
}
3.搜索
时间复杂度:O(N)
如果用户给的数有序,或者接近有序:时间复杂度:O(N),因为已经退化为单枝树
boolean contains(int key){
BSTnode cur=root;
while(cur!=null){
if(cur.value==key){
return true;
}
else if(cur.value<key){
cur=cur.right;
}else{
cur=cur.left;
}
}
return false;
}
4.最大节点
public int maxMostNode(){
BSTnode cur=root;
while(cur.right!=null){
cur=cur.right;
}
return cur.value;
}
5.最小节点
public int smallMostNode(){
BSTnode cur=root;
while(cur.left!=null){
cur=cur.left;
}
return cur.value;
}
6.二叉搜索树转化为有序的双向链表
双向链表:prev指向前一个节点 next指向后一个节点
按照中序遍历的规则来改变left和right的指向,left指向小的节点,right指向大的节点
1.找链表的首节点,也就是树中最小的节点----》最左端节点
2.按照中序遍历的规则来修改左右孩子的指向
每拿到一个节点,只修该当前节点的左指针域,因为按照中序遍历的规则,肯定知道当前节点的前一个节点是那个节点(因为其前一个节点刚刚遍历过),当前节点的后续还没有遍历
测试用例:
public class test {
public static void main(String[] args) {
int[] array=new int[]{5,3,7,1,4,6,8,0,2,9};
BSTree bsTree=new BSTree();
for(int e:array){
bsTree.put(e);
}
// bsTree.inOrderTree();
System.out.println(bsTree.contains(7));
System.out.println(bsTree.maxMostNode());
System.out.println(bsTree.smallMostNode());
bsTree.delete(6);
bsTree.inOrderTree();
}
}