*二叉搜索树的概念
二叉搜索树又称二叉排序树,它或许是一棵空树,或者具有以下性质的二叉树:
若它的左子树不为空,则左子树上所有节点的值都小于根节点的值;
若它的右子树不为空,则优子树上所有节点的值都大于根节点的值;
它的左右子数也分别为二叉搜索树
*查找
若根结点不为空:
如果根结点val==查找的val,返回true.
如果根结点val>查找的val,则在其左子树查找
如果根结点val<查找的val, 则在其右子树查找
具体代码实现:
//二叉搜索树的查找
public boolean serach(int val){
if(root==null){ //判断根节点是否为null
return false;
}
Node cur=root;
while(cur!=null){
if(cur.val==val){ //若根结点的val=查找值的val
return true;
}else if(cur.val>val){
cur=cur.left;
}else{
cur=cur.right;
}
}
return false;
}
*插入
若树为空树,即root==null,直接插入,然后返回true.
若树不是空树,按照查找逻辑确定插入顺序,插入新结点
具体代码实现:
//二叉搜索树的插入
public boolean insert(int val){
if(root==null){
root=new Node(val);
return true;
}
Node cur=root;
Node parent=null;
while(cur!=null){
if(cur.val==val){
return false; //注意不能插入相同的数字
}else if(cur.val>val){
parent= cur;
cur=cur.left;
}else{
parent= cur;
cur=cur.right;
}
}
if(parent.val>val){
parent.right=new Node(val);
}else{
parent.left=new Node(val);
}
return true;
}
***删除
1、若cur.left==null
若 cur是root,则root==cur.right;
若cur不是root,cur是parent.left,则parent.left=cur.right
若cur不是root,cur是parent.right,则parent.right=cur.right
2、cur.right=null
若 cur是root,则root==cur.left;
若cur不是root,cur是parent.left,则parent.left=cur.left
若cur不是root,cur是parent.right,则parent.right=cur.left
3、cur.right != null&&cur.lrft !=null
需要使用替换法删除,即在它的右子树下寻找最小节点,用它的值填补到要删除的节点
具体代码实现如下:
//二叉搜索树的删除
public boolean remove(int key){
if(root==null){
return false;
}
Node cur=root;
Node parent=null;
while(cur!=null){
if(cur.val<key){
parent=cur;
cur=cur.right;
}else if(cur.val>key){
parent=cur;
cur=cur.left;
}else{
removeNode(parent,cur);
return true;
}
}
return false;
}
public void removeNode(Node parent,Node cur){
if(cur.left==null){
if(cur==root){
root=cur.right;
}else if(parent.left==cur){
parent.left=cur.right;
}else{
parent.right=cur.right;
}
} else if(cur.right==null){
if(cur==root){
root=cur.left;
}else if(parent.left==cur){
parent.left=cur.left;
}else{
parent.right=cur.left;
}
}else{
Node target=cur.right;
Node targetParent=cur;
while(target.left!=null){
targetParent=target;
target=target.left;
}
cur.val=target.val;
if(target==targetParent.left){
targetParent.left=target.right;
}else{
targetParent.right=target.right;
}
}
}
二叉搜索树的查找、插入、和删除 完整代码:
public class BinarySearchTree {
public static class Node{
public int val;
public Node left;
public Node right;
public Node(int key){
this.val =val;
}
}
public Node root;
//二叉搜索树的查找
public boolean serach(int val){
if(root==null){ //判断根节点是否为null
return false;
}
Node cur=root;
while(cur!=null){
if(cur.val==val){ //若根结点的val=查找值的val
return true;
}else if(cur.val>val){
cur=cur.left;
}else{
cur=cur.right;
}
}
return false;
}
//二叉搜索树的插入
public boolean insert(int val){
if(root==null){
root=new Node(val);
return true;
}
Node cur=root;
Node parent=null;
while(cur!=null){
if(cur.val==val){
return false; //注意不能插入相同的数字
}else if(cur.val>val){
parent= cur;
cur=cur.left;
}else{
parent= cur;
cur=cur.right;
}
}
if(parent.val>val){
parent.right=new Node(val);
}else{
parent.left=new Node(val);
}
return true;
}
//二叉搜索树的删除
public boolean remove(int key){
if(root==null){
return false;
}
Node cur=root;
Node parent=null;
while(cur!=null){
if(cur.val<key){
parent=cur;
cur=cur.right;
}else if(cur.val>key){
parent=cur;
cur=cur.left;
}else{
removeNode(parent,cur);
return true;
}
}
return false;
}
public void removeNode(Node parent,Node cur){
if(cur.left==null){
if(cur==root){
root=cur.right;
}else if(parent.left==cur){
parent.left=cur.right;
}else{
parent.right=cur.right;
}
} else if(cur.right==null){
if(cur==root){
root=cur.left;
}else if(parent.left==cur){
parent.left=cur.left;
}else{
parent.right=cur.left;
}
}else{
Node target=cur.right;
Node targetParent=cur;
while(target.left!=null){
targetParent=target;
target=target.left;
}
cur.val=target.val;
if(target==targetParent.left){
targetParent.left=target.right;
}else{
targetParent.right=target.right;
}
}
}
public void inorder(Node root) {
if(root == null) return;
inorder(root.left);
System.out.print(root.val+" ");
inorder(root.right);
}
public void preOrder(Node root) {
if(root == null) return;
System.out.print(root.val+" ");
preOrder(root.left);
preOrder(root.right);
}
public static void main(String[] args) {
BinarySearchTree binarySearchTree
= new BinarySearchTree();
binarySearchTree.insert(15);
binarySearchTree.insert(2);
binarySearchTree.insert(35);
binarySearchTree.insert(9);
binarySearchTree.inorder(binarySearchTree.root);
System.out.println();
binarySearchTree.preOrder(binarySearchTree.root);
System.out.println("======================");
binarySearchTree.remove(9);
System.out.println("======================");
binarySearchTree.inorder(binarySearchTree.root);
System.out.println();
binarySearchTree.preOrder(binarySearchTree.root);
}
}
性能分析:
插入和删除操作都必须先查找,查找效率代表了 二叉搜索树的各个操作的性能。
对于n个节点的二叉搜索树,若每个元素查找的概率相等,则二叉搜索树平均查找长度是节点在二叉搜索树深度的函数,集结点越深,则比较次数越多。
但对于一个关键码的集合,如果各关键吗插入的次序不同,可能得到不同结构的二叉搜索树:完全二叉树和单支树。
最优情况下,二叉搜索树为完全二叉树,其平均比较次数为:log2n;
最差情况下,二叉搜索树化为单支树,其平均比较次数为:N/2