二叉搜索树的Java实现

为了更加深入了解二叉搜索树,本人用Java写了个二叉搜索树,有兴趣的同学可以一起探讨探讨。

  首先,二叉搜索树是啥?它有什么用呢?

  二叉搜索树, 也称二叉排序树,它的每个节点的数据结构为1个父节点指针,1个左孩子指针,1个有孩子指针,还有就是自己的数据部分了,因为只有左右两孩子,所以才叫二叉树,在此基础上,该二叉树还满足另外一个条件:每个结点的左孩子都不大于该结点&&每个结点的右孩子都大于该结点。这样,我们队这棵树进行中序遍历,就能把key从小到大排序了……

  那么问题来了,我都有线性表有链表了,我还要它干啥?两个字!效率

  相比线性表,你要搜索一个key,就要执行一次线性时间,算法复杂度为O(n);而用二叉搜索树,算法效率是O(lgn)!这是很诱人的数字。下面我用Java实现以下二叉搜索树,你自然就明白为什么算法复杂度是O(lgn)了。

  其次,写一个数据结构,自然而然也要实现对这个数据结构的增、删、查、改了。

  下面是我的思路:

创建树:我是通过一个一个结点的插入来建立一棵二叉搜索树。

搜索结点:从根节点开始,进行key的比较,小了就往左走,大了就往右走,最后到了叶子结点都还没有的话,那么该树就不存在要搜索的结点了。

修改结点:修改其实就是查询,在查询之后把结点的数据部分给改了而已,这里我就不重复去实现了。

删除结点:这个应该就是最难的了,所以我有必要详细讲,先上图(不好意思,懒得用软件画图了,将就将就下哈):

二叉搜索树的Java实现

当我们要删除一个结点时,分如下几种情况:

此结点是叶子结点,这个最简单啦,直接把结点给释放掉就行了。(如图删除9)

此结点只有左孩子,这个也简单啦,直接把左子树替换过来就行了。(如图删除3)

此结点只有右孩子,同上。(如图删除8)

此结点有左右孩子,当出现这种情况时(如图删除7),我们就要找出该结点的后继结点(因为右子树肯定存在,所以找肯定在右子树中),然后把这个后继结点替换到要删除的结点中,然后继续执行对这个后继结点的删除操作(递归删除操作就行了)。

 

  发现没?现在我的解题思路是自顶向下去分析……自顶向下,逐级求精是一个很伟大的思想!

 

  现在问题来了!后继结点怎么求?我们来分析一下,当求一个结点的后继结点时,分为以下两种情况:

当该结点有右孩子时,后继结点就在右子树中,就是该右子树的最小结点

当该结点没有右孩子时,那后继结点就满足这个条件:该后继结点是该结点的祖先&&该结点位于该结点的左子树中(如图中的9的后继结点是12)

  哎呀呀!问题又来了!最小结点咋办!很简单!

  当求一棵树的最小结点时,那么就要从这颗树的根节点开始,一直往左子树走,就能找到它的最小结点了!

  好了,现在问题逐步解决了!删除结点的功能也就完成了!

  最后,没代码说个锤子,咱上代码!

 

首先,写个测试类:

public class Test {
    public static void main(String[] args) {
        int[] datas={12,4,5,7,4,8,3,2,6,9};
        BinTree tree=new BinTree(datas);
        tree.preOrderTraverse();//先序遍历
        tree.midOrderTraverse();//中序遍历
        tree.postOrderTraverse();//后序遍历
        tree.insert(15);    //插入结点
        tree.search(7);        //查询结点
        tree.search(100);    //查询一个不存在的结点
        tree.getMax();        //获取最大值
        tree.getMin();        //获取最小值
        tree.getPre(7);        //前驱结点
        tree.getPre(2);        //最前的前驱结点
        tree.getPost(7);    //后继结点
        tree.getPost(15);    //最后的后继结点
        tree.delete(5);        //删除结点
        tree.delete(0);        //删除一个不存在的结点
    }
}

然后,二叉搜索树:

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/75bb65376b71197627b23e9b56907d70.html