数据结构树-->二叉查找树\二叉排序树

目录

1. 数据结构树–>树基础
2. 数据结构树–>二叉树
3. 数据结构树–>二叉查找树\二叉排序树
4. 数据结构树–>平衡二叉树
5. 数据结构树–>霍夫曼树
6. 数据结构树–>红黑树
7. 数据结构树–>二叉堆
8. 数据结构树–>B树
9. 数据结构树–>B+树

二叉查找树\二叉排序树

二叉查找树是一种有序的二叉树,也叫儿叉排序树,它在二叉树的基础上添加了位置排序的规则。
规则: 每颗子树的根节点值比左子树大,比右子树小。

在这里插入图片描述

二叉查找树的缺点: 二叉查找树有了排序,但当我们的数据顺序与大小规律一致是就会发现,二叉查找树基本退化为了链表,导致达不到二叉

查找树快速查找的目的。

在这里插入图片描述

后续我们在介绍平衡二叉树的时候会解决之一问题。

1. 二叉查找树的查找

更具儿叉查找树的特性二叉查找树查找元素快速简单,快速:二叉查找树查找基本就是二分查找,所以快速。

2. 二叉查找树的插入

首先二叉查找树新插入的节点必定是新叶子节点。

在这里插入图片描述

如图,节点6并不会插入到节点5与节点7之间,而是插入到节点5的右孩子节点,新的节点是新叶子节点。

3. 二叉查找树的删除

二叉查找树的删除就有点复杂了,删除节点会破坏二叉查找树的结构,我们删除完节点后需要恢复该结构,在充分理解了二叉树的特性后你又能很容易的理解。

需要理解的特性:每颗子树的根节点的值比左子树大,比右子树小。

  1. 据特性1,我们能推倒出每颗子树可以一直向左查找,查到叶子节点就是该子树的最小值,一直向右查找,查到叶子节点就是该子树的最大值。

二叉查找树的删除分三种情况:

  1. 删除的节点是叶子节点。
  2. 删除的节点只有一个子树。
  3. 删除的节点有两个子树。

3.1 删除的节点是叶子节点

这个很简单,我们了解叶子节点的特性,叶子节点可以直接删除不会破坏查找树的结构。

3.2 删除的节点只有一个子树

我们了解的二叉查找树的特性,如果一个节点只有一个子树,那么这个子树不管是左子树还是右子树,这个子树直接赋值到该节点的父节点上也是不会破坏

查找树的结构的。

在这里插入图片描述

如图删除节点4,根据二叉查找树排序的特性我们知道节点4的子树相对于它的父节点的排序与结构特性也是符合的,所以我们就可以将节点4的子树直接按照

节点4相对于节点4的父节点的左右区分赋值给节点4的父节点。也就是节点4属于父节点的左子树,删除节点4,节点4的子树赋值给父节点的左子树。

节点4属于父节点的右子树,子树就赋值给父节点的右子树,不用区分子树是属于节点4的左子树还是右子树。

3.3 删除的节点有两个子树

在这里插入图片描述

如图当我们要删除节点3的时候就会破坏二叉查找树的结构,我们删除后需要恢复该节点的结构。怎么恢复呢?需要确认那个节点来代替节点3的位置,如果使用右子树根节点5

来代替那节点4就需要动,使用左子树同样会出现这个问题。

我们了解二叉查找树的特性,每颗子树的根节点大于所有左子树,小于所有右子树,我们需要在左右子树中找出符合这个特性的节点来替代节点3,这个替代过程也要简单无需移动

太多。符合这个要求的节点我们根据二叉查找树的特性就能找到,最好的节点就是要删除的节点3的左子树最大值,右子树的最小值,也就是左子树的最右叶子节点,右子树的最左

叶子节点。我们通常使用的是右子树的最左节点(最小值)来替代节点3。

3.4 java 代码实现

   public static void delete(BinaryTreeNode root, int key) {
        BinaryTreeNode father = root;
        BinaryTreeNode delete = null;
        //delete节点属于father的那个方向
        boolean left = true;
        while (father != null) {
            if (father.getKey() < key) {
                if (father.getRight() != null && father.getRight().getKey() == key) {
                    delete = father.getRight();
                    left = false;
                    break;
                } else {
                    father = father.getRight();
                }
            } else {
                if (father.getLeft() != null && father.getLeft().getKey() == key) {
                    delete = father.getLeft();
                    left = true;
                    break;
                } else {
                    father = father.getLeft();
                }
            }
        }

        if (father != null) {
            System.out.println("father key=" + father.getKey() + "      delete key=" + delete.getKey());
            BinaryTreeNode l = delete.getLeft();
            BinaryTreeNode r = delete.getRight();
            if (l == null && r == null) {
                //删除的节点是叶子节点
                if (left) {
                    father.setLeft(null);
                } else {
                    father.setRight(null);
                }
            } else if (l == null || r == null) {
                //删除的节点只有一个子树
                if (left) {
                    if (l == null) {
                        father.setLeft(delete.getRight());
                    } else {
                        father.setLeft(delete.getLeft());
                    }
                } else {
                    if (l == null) {
                        father.setRight(delete.getRight());
                    } else {
                        father.setRight(delete.getLeft());
                    }
                }
            } else {
                //删除的节点有两个子树
                //找到右子树的最小值
                BinaryTreeNode tempFather = delete;
                BinaryTreeNode min = null;
                Stack<BinaryTreeNode> temps = new Stack<>();
                temps.add(tempFather);
                tempFather = tempFather.getRight();
                while (true) {
                    temps.push(tempFather);
                    if (tempFather.getLeft() == null) {
                        break;
                    } else {
                        tempFather = tempFather.getLeft();
                    }
                }
                min = temps.pop();
                tempFather = temps.pop();

                if (left) {
                    father.setLeft(min);
                } else {
                    father.setRight(min);
                }

                if (temps.size() > 0) {
                    //这个判断 tempFather 不是为delete节点 如果最小值有右子树则赋值右子树。
                    if (min.getRight() != null) {
                        tempFather.setLeft(min.getRight());
                    }
                    min.setLeft(delete.getLeft());
                    min.setRight(delete.getRight());
                } else {
                    if (min.getRight() != null) {
                        tempFather.setRight(min.getRight());
                    }
                    min.setLeft(delete.getLeft());
                }

            }
        }
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值