查找-二叉查找树

源码:https://github.com/sunrui849/selectAlgorithm

目录:顺序查找

二分查找

插值查找

斐波那契查找

分块查找

哈希查找

二叉树查找

红黑树查找

二叉查找树(Binary Search Tree)

二叉查找树又称二叉排序树又称二叉搜索树,如不为空则有以下性质:

1. 若任意节点的左子树不空,则左子树上所有结点的值均小于它的根结点的值;

2. 若任意节点的右子树不空,则右子树上所有结点的值均大于它的根结点的值;

3. 任意节点的左、右子树也分别为二叉查找树。

这里有个比较好的网址,可以自己手动增删查进行操作,观察动画方便理解
https://www.cs.usfca.edu/~galles/visualization/Algorithms.html

如下图:

增加

从根节点开始比较,如果大于该节点则到右子节点比较,否则到左子节点比较,直到碰到节点为空时,将要增加的节点赋值到空节点上,对于相等时的处理,可以直接插入到右侧或左侧的节点上。或者可以采用递归来实现。

/**
     *向二叉搜索树中增加一个元素
     * @param value
     * @return
     */
    public boolean put(int value){
        if (this.value == null){
            this.value = value;
            return true;
        }
        BinarySortTree tree = this;
        while (true){
            if (value > tree.value) {
                if (tree.rightNode == null){
                    tree.rightNode = new BinarySortTree(tree,null,null,value);
                    break;
                }
                tree = tree.rightNode;
            }else if(value < tree.value){
                if (tree.leftNode == null){
                    tree.leftNode = new BinarySortTree(tree,null,null,value);
                    break;
                }
                tree = tree.leftNode;
            }else {
                tree.rightNode = new BinarySortTree(tree,null,tree.rightNode,value);
                break;
            }
        }
        return true;
    }

查找

查找是比较方便的,不断和节点值比较,大于节点值就到右子树比较,小于节点值就到左子树比较,直到相等即可结束

 /**
     * 查找第一个出现该值的节点
     * @param value
     * @return
     */
    public BinarySortTree get(int value){
        BinarySortTree tree = this;

        if (this.value == null){
            return null;
        }

        while (tree != null){
            if (tree.value == value){
                return tree;
            } else if (tree.value > value){
                tree = tree.leftNode;
            } else{
                tree = tree.rightNode;
            }
        }
        return null;
    }

删除

删除节点主要分为三种情况,

1.节点无子节点,直接删除即可

2.节点有一个子节点,子节点上提即可

3.节点有两个子节点,可随意上提一个子树,如上提的是左子树(右子树),并将另一侧节点放到上提的子树中最大节点(最小节点)的右节点(左节点)上


    /**
     * 删除第一个节点的值是该值的节点
     * @param value
     * @return
     */
    public boolean remove(int value){

        if (this.value == null){
            return false;
        }
        BinarySortTree tree = this;
        while (tree != null) {
            if (tree.value > value){
                tree = tree.leftNode;
            }else if (tree.value < value){
                tree = tree.rightNode;
            }else {
                remove(tree);
                return true;
            }
        }
        return false;
    }

    private void remove(BinarySortTree tree){

        //删除
        if (tree.leftNode == null && tree.rightNode == null){
            //左右节点都为空,直接把父节点指向置空即可
            if (tree.parentNode == null){
                //根节点
                tree.value = null;
            }else if (tree.parentNode.leftNode == tree){
                tree.parentNode.leftNode = null;
            }else {
                tree.parentNode.rightNode = null;
            }
        }else if (tree.leftNode == null){
            //右节点不为空,左节点为空
            if (tree.parentNode == null){
                //根节点
                tree.value = tree.rightNode.value;
                tree.leftNode = tree.rightNode.leftNode;
                tree.rightNode = tree.rightNode.rightNode;
            }else if (tree.parentNode.leftNode == tree){
                tree.parentNode.leftNode = tree.rightNode;
            }else {
                tree.parentNode.rightNode = tree.rightNode;
            }
        }else if (tree.rightNode == null){
            //左节点不为空,右节点不为空
            if (tree.parentNode == null){
                //根节点
                tree.value = tree.leftNode.value;
                tree.rightNode = tree.leftNode.rightNode;
                tree.leftNode = tree.leftNode.leftNode;
            }else if (tree.parentNode.leftNode == tree){
                tree.parentNode.leftNode = tree.leftNode;
            }else {
                tree.parentNode.rightNode = tree.leftNode;
            }
        }else{
            //左右节点都不为空,将左节点上提,右节点放到左节点最右的节点后
            if (tree.parentNode == null){
                BinarySortTree leftNodeTreeMaxNode = tree.leftNode;
                while (leftNodeTreeMaxNode.rightNode != null){
                    leftNodeTreeMaxNode = leftNodeTreeMaxNode.rightNode;
                }
                leftNodeTreeMaxNode.rightNode = tree.rightNode;
                tree.value = tree.leftNode.value;
                tree.rightNode = tree.leftNode.rightNode;
                tree.leftNode = tree.leftNode.leftNode;
            }else if (tree.parentNode.leftNode == tree){
                tree.parentNode.leftNode = tree.leftNode;
                BinarySortTree leftNodeTreeMaxNode = tree.leftNode;
                while (leftNodeTreeMaxNode.rightNode != null){
                    leftNodeTreeMaxNode = leftNodeTreeMaxNode.rightNode;
                }
                leftNodeTreeMaxNode.rightNode = tree.rightNode;
            }else {
                tree.parentNode.rightNode = tree.leftNode;
                BinarySortTree leftNodeTreeMaxNode = tree.leftNode;
                while (leftNodeTreeMaxNode.rightNode != null){
                    leftNodeTreeMaxNode = leftNodeTreeMaxNode.rightNode;
                }
                leftNodeTreeMaxNode.rightNode = tree.rightNode;
            }
        }
    }

遍历

直接上代码


    /********三种遍历************
     *          A
     *         / \
     *       B    E
     *        \    \
     *         C    F
     *        /    /
     *       D    G
     *          /\
     *         H  K
     *
     * 前序遍历(根左右): ABCDEFGHK
     * 中序遍历(左根右): BDCAEHGKF
     * 后序遍历(左右根): DCBHKGFEA
     *
     * */

    /**
     * 后序遍历,最后一个一定是根节点
     * @return
     */
    public List<Integer> endIteration(){
        List<Integer> list = new ArrayList<Integer>();
        endRecursion(this,list);
        return list;
    }

    private void endRecursion(BinarySortTree tree,List<Integer> list){
        if (tree == null || tree.value == null){
            return;
        }
        endRecursion(tree.leftNode, list);
        endRecursion(tree.rightNode, list);
        list.add(tree.value);
    }

    /**
     * 中序遍历,第一个是最小值,最后一个是最大值
     * @return
     */
    public List<Integer> middleIteration(){
        List<Integer> list = new ArrayList<Integer>();
        middleRecursion(this,list);
        return list;
    }

    private void middleRecursion(BinarySortTree tree,List<Integer> list){
        if (tree == null || tree.value == null){
            return;
        }
        middleRecursion(tree.leftNode, list);
        list.add(tree.value);
        middleRecursion(tree.rightNode, list);
    }


    /**
     * 前序遍历,第一个一定是根节点
     * @return
     */
    public List<Integer> beforeIteration(){
        List<Integer> list = new ArrayList<Integer>();
        beforeRecursion(this,list);
        return list;
    }

    private void beforeRecursion(BinarySortTree tree,List<Integer> list){
        if (tree == null || tree.value == null){
            return;
        }
        list.add(tree.value);
        beforeRecursion(tree.leftNode, list);
        beforeRecursion(tree.rightNode, list);
    }

 

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值