Java笔记:二叉搜索树(BST)

二叉搜索树

二叉搜索树(Binary Search Tree, BST):左子树的节点值小于根节点的值,右子树的节点值大于根节点的值,且没有重复节点。
Java笔记:二叉搜索树(BST)_第1张图片

1 二叉搜索树插入数据

二叉搜索树插入数据(5、11、22)举例(插入任何数据都能够在叶子节点上完成插入):
Java笔记:二叉搜索树(BST)_第2张图片

public class TestBinaryTree {
    //静态节点
    static class Node{
        public int data;
        public Node left;
        public Node right;

        public Node(int data) {
            this.data = data;
            this.left = null;
            this.right = null;
        }
    }
    public Node root = null;
    //插入(其实就是找叶子节点,且插入位置不在叶子节点左边就是在叶子节点右边)
    public void insert(int key) {
        Node node = new Node(key);
        Node cur = root;
        Node parent =null;
        if(root==null){
            root=node;
            return;
        }
        //找叶子节点(parent)(正确的插入节点)
        while(cur!=null){
            if(cur.data>node.data){
                parent=cur;
                cur=cur.left;
            }else if(cur.data<node.data){
                parent=cur;
                cur=cur.right;
            }else{
                //cur.data=node.data的情况需要排除掉
                return;
            }
        }
        //开始插入
        //parent.data>node.data时,在左边插入
        if(parent.data>node.data){
            parent.left=node;
        }else{
          //  parent.data
            parent.right=node;
        }
    }
    //查找
    public Node search(int key){
        Node cur = root;
        while(cur!=null){
            if(key<cur.data){
                cur=cur.left;
            }else if(key==cur.data){
                return cur;
            } else{
                cur=cur.right;
            }
        }
        return null;
    }
    //前序遍历
    public void preOrder(Node root){
        if(root!=null){
            System.out.print(root.data+" ");
            preOrder(root.left);
            preOrder(root.right);
        }
    }
    //中序遍历
    public void inOrder(Node root){
        if(root!=null){
            inOrder(root.left);
            System.out.print(root.data+" ");
            inOrder(root.right);
        }
    }

2 二叉搜索树删除数据

(1)首先要找到要删除的节点cur及其父节点parent

//删除关键字为key的节点
    public void remove(int key) {
        Node cur = root;
        Node parent = null;
        while (cur != null) {
            if(cur.data == key) {
                //找到要删除的节点,及其父节点,然后进行删除
                removeNode(parent,cur);
                return;
            }else if(cur.data < key) {
                parent = cur;
                cur = cur.right;
            }else {
                parent = cur;
                cur = cur.left;
            }
        }
    }

(2)删除数据分三种情况:

1)cur.left==null

cur==root,则root=cur.right;
cur!=root,若cur在父节点的左边,则parent.left=cur.right;
cur!=root,若cur在父节点的右边,则paretn.right=cur.right;

cur.left==null且cur在parent的左边的情况:
Java笔记:二叉搜索树(BST)_第3张图片
2)cur.right==null

cur==root,则root=cur.left;
cur!=root,若cur在父节点的左边,则parent.left=cur.left;
cur!=root,若cur在父节点的右边,则paretn.right=cur.left;

cur.right==null且cur在parent的右边:
Java笔记:二叉搜索树(BST)_第4张图片
3)cur.right!=null&&cur.left!=null
要用替换法解决,即选择左树值最大的target节点进行替换,或选择右树值最小的target节点进行替换,最后需要删除target节点(其实cur节点并未被删除,只是值被改变)。

下面以取右边的最小值举例:
Java笔记:二叉搜索树(BST)_第5张图片

Java笔记:二叉搜索树(BST)_第6张图片

public void removeNode(Node parent,Node cur){
        if(cur.left == null) {
            if(cur == root) {
                root=cur.right;
            }else if(cur == parent.left){
                parent.left=cur.right;
            }else { //cur == parent.right
                parent.right = cur.right;
            }
        }else if(cur.right == null) {
            if(cur == root) {
                root=cur.left;
            }else if(cur == parent.left){
                parent.left=cur.left;
            }else { //cur == parent.right
                parent.right = cur.left;
            }
        }else {
            Node targetParent = cur;
            //记录真正要删除节点的父亲节点
            //(即左树最大值或右树最小值的父节点)
            //在右边找最小值
            Node target = cur.right;
            while (target.left != null) {
                targetParent = target;
                target = target.left;
            }

            cur.data = target.data;
            //target的左肯定是空的
            if(target == targetParent.left) {
            	//target.right可能为空,也可能不为空
                targetParent.left = target.right;
            }else {
                targetParent.right = target.right;
            }
        }
    }

小记:

  1. 二叉搜索树的深度代表了二叉搜索树的时间复杂度,节点越深,则比较次数越多。
  2. 最优情况下,二叉搜索树为完全二叉树,其平均比较次数为log2N.
  3. 最坏情况下,二叉搜索树为单支树,其平均比较次数为N/2.
  4. 同样的一组数据,组成二叉搜索树的次序不同,会造成其节点深度不同。

你可能感兴趣的:(Java)