二叉搜索树创建和删除

书读的越多而不加思考,你就会觉得你知道得很多;而当你读书而思考得越多的时候,你就会越清楚地看到,你知道得很少。

导读:本篇文章讲解 二叉搜索树创建和删除,希望对大家有帮助,欢迎收藏,转发!站点地址:www.bmabk.com,来源:原文

二叉搜索树

也叫二叉排序树,它的递归定义为:
1.如果树T的左子树非空,则左子树中的所有结点的值小于T的根节点的值;
2.如果树T的右子树非空,则右子树中的所有结点的值大于T的根节点的值;
3.树T的左子树和右子树均为二叉搜索树

例子:
在这里插入图片描述
这棵树不是二叉搜索树
在这里插入图片描述

二叉搜索树的创建

算法思想:先树中搜索插入的key是否存在,如果存在就用当前的value替换树中的value,如果不存在,就在最后的位置插入一个结点

创建树结点的类:

public class BinarySearchNode<V> {
    public int key;
    public V value;
    public BinarySearchNode<V> leftNode;
    public BinarySearchNode<V> rightNode;

    public BinarySearchNode(int key, V value) {
        this.key = key;
        this.value = value;
    }
}

设定key为整型,value为指定的类型

创建二叉搜索树的类:

public class MyBinarySearchTree<V> {
    private BinarySearchNode<V> root = null;
}

具体算法:
1.判断树是不是空树,如果是空树就创建一根结点

if (root == null) {
    root = new BinarySearchNode<V>(key, value);
    return;
}

2.如果不是空树,遍历一下树,找一下树中有没有跟插入的数据相同的结点,如果有,修改一下值,如果没有就插入,所以需要记录当前结点的父结点,因为最后是插在父结点的位置上

BinarySearchNode<V> cur = root;
BinarySearchNode<V> parent = null;
while (cur != null) {
     if (key < cur.key) {
         parent = cur;
         cur = cur.leftNode;
     } else if (key > cur.key) {
         parent = cur;
         cur = cur.rightNode;
     } else {
     	 // 找到了相同key的结点
     	 // 修改结点的值即可
         cur.value = value;
         return;
     }
}

3.循环结束,没有相同的值,在父结点的位置上进行插入一个结点

if (key < parent.key) {
    parent.leftNode = new BinarySearchNode<V>(key, value);
} else {
    parent.rightNode = new BinarySearchNode<V>(key, value);
}

最后的插入函数:

public void insert(int key, V value) {
        if (root == null) {
            root = new BinarySearchNode<V>(key, value);
            return;
        } else {
            BinarySearchNode<V> cur = root;
            BinarySearchNode<V> parent = null;
            while (cur != null) {
                if (key < cur.key) {
                    parent = cur;
                    cur = cur.leftNode;
                } else if (key > cur.key) {
                    parent = cur;
                    cur = cur.rightNode;
                } else {
                    cur.value = value;
                    return;
                }
            }
            if (key < parent.key) {
                parent.leftNode = new BinarySearchNode<V>(key, value);
            } else {
                parent.rightNode = new BinarySearchNode<V>(key, value);
            }
            return;
        }
    }

图示:
对这颗树插入key = 18的结点
在这里插入图片描述
18小于cur所指向的结点的key
即 18 < 20
所以在左子树进行查找
在这里插入图片描述
16 < 18 所以在右子树查找
在这里插入图片描述

此时cur的右子树为空,所以要插入一个结点
插入的位置是parent的右子树
在这里插入图片描述

二叉搜索树的删除

算法思想:
设cur为当前要被删除的结点,parent为cur的父结点
1.cur结点没有左子树 (cur.left == null
1.1 cur是根结点 (cur == root
在这里插入图片描述

删除操作:

root = cur.right;

1.2 cur不是根结点,cur是parent的右子树
cur != root && cur == parent.right
在这里插入图片描述
删除操作:

parent.right = cur.right;

1.3 cur不是根结点,cur是parent的左子树
cur != root && cur == parent.left
在这里插入图片描述
删除操作:

parent.left = cur.right;

2.cur的右子树为空(cur.right == null
2.1 cur是根结点 (cur == root
在这里插入图片描述
删除操作:

root = cur.left;

2.2 cur不是根结点,cur是parent的右子树
cur != root && cur == parent.right
在这里插入图片描述
删除操作:

parent.right = cur.left;

2.3 cur不是根结点,cur是parent的左子树
cur != root && cur == parent.left
在这里插入图片描述
删除操作:

parent.left = cur.left;

3.cur的左右子树都不为空
删除步骤:下面两个选择一个
(1)在左子树中找到最大值的结点,用该结点的值于cur的值进行交换,之后将最大值结点从它的父结点上删除
(2)在右子树中找到最小值的结点,用该结点的值于cur的值进行交换,之后将最小值结点从它的父结点上删除

用(2)举例子:
goat为最值结点(最小值结点)
parenr为goat的父结点
在这里插入图片描述
删除操作:

if (goat == parent.left) {
    parent.left = goat.right;
} else {
    parent.right = goat.right;
}

具体删除函数

public void remove(int key) {
        BinarySearchNode<V> cur = root;
        BinarySearchNode<V> parent = null;
        while (cur != null) {
            if (key < cur.key) {
                parent = cur;
                cur = cur.leftNode;
            } else if (key > cur.key) {
                parent = cur;
                cur = cur.rightNode;
            } else {
                removeNode(parent, cur);
                return;
            }
        }
    }

    private void removeNode(BinarySearchNode<V> parent, BinarySearchNode<V> cur) {
        if (cur.leftNode == null) {
            if (cur == root) {
                root = cur.rightNode;
            } else if (cur != root) {
                parent.rightNode = cur.rightNode;
            } else {
                parent.leftNode = cur.rightNode;
            }
        } else if (cur.rightNode == null) {
            if (cur == root) {
                root = cur.leftNode;
            } else if (cur != root) {
                parent.rightNode = cur.leftNode;
            } else {
                parent.leftNode = cur.leftNode;
            }
        } else {
            BinarySearchNode<V> goat = cur;
            BinarySearchNode<V> goatParent = parent;
            while (goat.leftNode != null) {
                goatParent = goat;
                goat = goat.leftNode;
            }
            cur.key = goat.key;
            cur.value = goat.value;
            if (goat == goatParent.leftNode) {
                goatParent.leftNode = goat.rightNode;
            } else {
                goatParent.rightNode = goat.rightNode;
            }
        }
}

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/122860.html

(0)
飞熊的头像飞熊bm

相关推荐

发表回复

登录后才能评论
极客之音——专业性很强的中文编程技术网站,欢迎收藏到浏览器,订阅我们!