二叉搜索树
今天简单的说一下二叉搜索树,为什么叫做二叉搜索树呢?从名字我们就能看出来,用它进行查询操作会很方便。
二叉搜索树的一些特性:
1:二叉搜索树的中序遍历是一个有序的序列
2:二叉搜索树也可以是一棵空树
3:若它的左子树不为空,那么它的左子树上的所有节点的值都小于根节点的值。
4:若它的右子树不为空,那么它的右子树上的所有节点的值都大于根节点的值。
5:二叉搜索树的左右子树也是二叉搜索树。
6:二叉搜索树中最左侧的节点一定是最小的节点,最右侧的节点一定是最大的节点。
关于二叉搜索树的一些操作
我们知道可以在二叉搜索树中查找元素,插入元素,删除元素等等。
我认为,一切基于查询的基础上进行一些操作。
给张图,可能看着更好理解,哈哈。
下面是查询元素的代码
public static class Node{
private Node left;
private Node right;
int val;
public Node(int val){
this.val=val;
}
}
public Node root=null;
//是否包含给定值
public boolean contains(int val){
if(root==null){
throw new IllegalArgumentException();
}
Node cur=root;
while (cur!=null){
if (cur.val==val){
return true;
}else if (cur.val>val){
cur=cur.left;
}else {
cur=cur.right;
}
}
return false;
}
用到了静态内部类来创建一个节点对象,是不是很方便啊,哈哈哈。
下面是插入操作,插入元素在查询的基础上增加了一点代码,但是还是大同小异,但是要注意我们要用一个节点来保存待插入节点的前驱,意思不太准确,学过单链表就应该懂我的意思。
下面是插入的代码:
//插入,要知道待插入节点的父节点
public boolean put(int val){
if(root==null){
throw new IllegalArgumentException();
}
Node cur = root;
Node parent=null;
while(cur!=null){
parent=cur;
if(cur.val==val){
return false;
}else if (cur.val>val){
cur=cur.left;
}else {
cur=cur.right;
}
}
//要插入的节点
cur=new Node(val);
if(parent.val>val){
parent.left=cur;
}
else {
parent.right=cur;
}
return true;
}
删除就相对麻烦了点,关键是分的情况太多了,话不多说,上代码,我在代码里面都注释了。
public boolean remove(int val){
//如果root为空
if(null==root){
throw new IllegalArgumentException();
}
//遍历搜索树,找到与val值相等的节点结束循环
//用一个节点保存待删除节点的父节点
Node cur=root;
Node parent=null;
while (cur!=null){
if(val>cur.val){
parent=cur;
cur=cur.right;
}else if (val<cur.val){
parent=cur;
cur=cur.left;
}else {
break;
}
}
if(cur==null){
return false;
}
//已经找到待删除节点,现在分情况
//1:cur只有左孩子
if(cur.right==null){
//只有左孩子并且cur为头结点
if(parent==null){
root=cur.left;
return true;
}else {
//只有左孩子cur不是头结点
parent.left=cur.left;
return true;
}
}
//2:cur只有右孩子
if(cur.left==null){
//只有右孩子并且cur为头结点
if(parent==null){
root=cur.right;
return true;
}else {
//只有右孩子cur不是头结点
parent.right=cur.right;
return true;
}
}
//3:cur左右孩子均存在
//不能直接删除,在它的子树中找一个替代节点
//左子树:找左子树中最大的节点(最右侧节点)
//右子树:找右子树中最小的节点(最左侧节点)
Node del=cur.right;
parent=cur;
while (del.left!=null){
parent=del;
del=del.left;
}
//替代节点找到
cur.val=del.val;
//删除这个节点,相当于替代节点到了cur的位置
//再把最下面的替代节点删掉,转换思维,就是删掉了cur
if(del==parent.left){
parent.left=del.right;
return true;
}else {
parent.right=del.right;
return true;
}
}
看了这代码是不是想打人,淡定,其实我和你是一样的心情,可能有更好的方式,希望大家发现错误指出来,一起学习进步,奥利给。