二叉搜索树的实现

简介: 二叉搜索树的实现

@TOC

什么是搜索树?

二叉搜索树又称二叉排序树,它或者是一棵空树,或者是具有以下性质的二叉树:

1.若它的左子树不为空,则左子树上所有节点的值都小于根节点的值
2.若它的右子树不为空,则右子树上所有节点的值都大于根节点的值
3.它的左右子树也分别为二叉搜索树

在这里插入图片描述

查找操作

在这里插入图片描述
这里我们定义一个cur指针用来遍历搜索树。

//查找key是否存在
    public TreeNode search(int key) {
        TreeNode cur = root;
        while(cur != null) {
            if(cur.key == key) {
                return cur;
            }else if(cur.key > key){
                cur = cur.left;
            }else {
                cur = cur.right;
            }
        }
        return null;
    }

插入操作

  1. 如果树为空树,即根 == null,直接插入

在这里插入图片描述

  1. 如果树不是空树,按照查找逻辑确定插入位置,插入新结点

在这里插入图片描述
定义一个cur去遍历搜索树,parent用来记录cur的上一位置,如果该结点大于key则遍历左子树,小于遍历右子树,等于直接退出(搜索树不允许出现相同的数值)。

public boolean insert(int key) {
        if(root == null) {
            root = new TreeNode(key);
        }
        TreeNode prev = null;
        TreeNode cur = root;
        while(cur != null) {
            if(cur.key == key) {
                return false;
            }else if(cur.key > key) {
                prev = cur;
                cur = cur.left;
            }else {
                prev = cur;
                cur = cur.right;
            }
        }
        if(prev.key > key) {
            prev.left = new TreeNode(key);
        }else {
            prev.right = new TreeNode(key);
        }
        return true;
    }

删除操作

设待删除结点为 cur, 待删除结点的双亲结点为 parent

分三种情况:
1.cur.left == null

  1. cur 是 root,则 root = cur.right
  2. cur 不是 root,cur 是 parent.left,则 parent.left = cur.right
  3. cur 不是 root,cur 是 parent.right,则 parent.right = cur.right

2.cur.right == null

  1. cur 是 root,则 root = cur.left
  2. cur 不是 root,cur 是 parent.left,则 parent.left = cur.left
  3. cur 不是 root,cur 是 parent.right,则 parent.right = cur.left

3. cur.left != null && cur.right != null
需要使用替换法进行删除,即在它的右子树中寻找中序下的第一个结点(关键码最小),用它的值填补到被删除节点中,再来处理该结点的删除问题

第一和第二种情况相对比较简单,改变一下parent的指向即可,我们具体讨论一下第三种情况。

在这里插入图片描述
如果我们想从上面的 搜索树 中删除 15,我们可以做一些技巧来将情况减少到情况 1 或情况 2
1.求其右子树的最小值
2.求其左子树的最大值
在这里插入图片描述
我们可以发现我们只需要找到右子树的最左的,或者左子树最右的和cur交换即可,不影响搜索树的顺序。

public boolean remove(int key) {
        TreeNode prev = null;
        TreeNode cur = root;
        while(cur != null) {
            if(cur.key == key) {
                removeChild(prev,cur);
                return true;
            }else if(cur.key > key) {
                prev = cur;
                cur = cur.left;
            }else {
                prev = cur;
                cur = cur.right;
            }
        }
        return false;
    }
    public  void removeChild(TreeNode parent,TreeNode cur) {
        if(cur.left == null) {
            if(cur == root) {
                root = root.right;
            } else if(cur == parent.left) {
                parent.left = cur.right;
            }else {
                parent.right = cur.right;
            }
        }else if(cur.right == null) {
            if(cur == root) {
                root = root.left;
            }else if(cur == parent.left) {
                parent.left = cur.left;
            }else {
                parent.right = cur.left;
            }
        }else {
            TreeNode target = cur.right;
            TreeNode targetParent = cur;
            while(target.left != null) {
                targetParent = target;
                target = target.left;
            }
            cur.key = target.key;
            if(target == targetParent.left) {
                targetParent.left = target.right;
            }else {
                targetParent.right = target.right;
            }
        }
    }

实现

public class BinarySearchTree {
    static class TreeNode {
        public int key;
        public TreeNode left;
        public TreeNode right;

        public TreeNode(int key) {
            this.key = key;
        }

        @Override
        public String toString() {
            return "TreeNode{" +
                    "key=" + key +
                    '}';
        }
    }

    public TreeNode root;

    /**
     * 插入一个元素
     */
    public boolean insert(int key) {
        if(root == null) {
            root = new TreeNode(key);
        }
        TreeNode prev = null;
        TreeNode cur = root;
        while(cur != null) {
            if(cur.key == key) {
                return false;
            }else if(cur.key > key) {
                prev = cur;
                cur = cur.left;
            }else {
                prev = cur;
                cur = cur.right;
            }
        }
        if(prev.key > key) {
            prev.left = new TreeNode(key);
        }else {
            prev.right = new TreeNode(key);
        }
        return true;
    }

    public  void inOrder(TreeNode root) {
        if(root == null) {
            return;
        }
        inOrder(root.left);
        System.out.println(root.key + " ");
        inOrder(root.right);
    }
    //查找key是否存在
    public TreeNode search(int key) {
        TreeNode cur = root;
        while(cur != null) {
            if(cur.key == key) {
                return cur;
            }else if(cur.key > key){
                cur = cur.left;
            }else {
                cur = cur.right;
            }
        }
        return null;
    }

    public boolean remove(int key) {
        TreeNode prev = null;
        TreeNode cur = root;
        while(cur != null) {
            if(cur.key == key) {
                removeChild(prev,cur);
                return true;
            }else if(cur.key > key) {
                prev = cur;
                cur = cur.left;
            }else {
                prev = cur;
                cur = cur.right;
            }
        }
        return false;
    }
    public  void removeChild(TreeNode parent,TreeNode cur) {
        if(cur.left == null) {
            if(cur == root) {
                root = root.right;
            } else if(cur == parent.left) {
                parent.left = cur.right;
            }else {
                parent.right = cur.right;
            }
        }else if(cur.right == null) {
            if(cur == root) {
                root = root.left;
            }else if(cur == parent.left) {
                parent.left = cur.left;
            }else {
                parent.right = cur.left;
            }
        }else {
            TreeNode target = cur.right;
            TreeNode targetParent = cur;
            while(target.left != null) {
                targetParent = target;
                target = target.left;
            }
            cur.key = target.key;
            if(target == targetParent.left) {
                targetParent.left = target.right;
            }else {
                targetParent.right = target.right;
            }
        }
    }
}
目录
相关文章
|
6月前
二叉搜索树
二叉搜索树
30 2
|
1月前
|
API 调度
二叉排序树
二叉排序树
23 0
|
5月前
|
C++
【c++】二叉搜索树
【c++】二叉搜索树
36 0
|
6月前
|
存储 安全 C++
C++【二叉搜索树】
C++【二叉搜索树】
61 0
51 # 二叉搜索树的实现
51 # 二叉搜索树的实现
34 0
|
存储 算法 关系型数据库
有了二叉树,平衡二叉树为什么还需要红黑树
有了二叉树,平衡二叉树为什么还需要红黑树
101 0
有了二叉树,平衡二叉树为什么还需要红黑树
|
编译器 C语言 C++
【C++】二叉搜索树
【C++】二叉搜索树
71 0
|
存储
【二叉搜索树】
【二叉搜索树】
48 0
|
算法
二叉搜索树、平衡二叉树
一、二叉搜索树 这里我们不用太多书面化的语言来定义,笔者认为在讨论数据结构、算法相关的内容时用太多书面化、学术化的语言是一种让人很烦的事情。咬文嚼字,不便于读者理解。 简单来说二叉树搜索树,其实就是用来做二分查找的一种二叉树。 特点是:根节点的左子树值均小于根节点的值,根节点的右子树值均大于根节点的值。 比如123 4 567建树的结果就是
56 0