数据结构:二叉搜索树(BST)的基本操作

概述:

  学习过数据结构的童鞋都应该知道,对树的操作是一些最基本的技能(本文是对后面要写B树、B-树、B+树的一个前导,已经熟悉的朋友可以跳过了)。而在树结构中,二叉树又是最基础的。虽然这些知识是比较基础的,不过对于BST的操作中,删除是一个相对比较麻烦的。这对于新手来说可能不太好理解,下面就以BST中节点的删除为主,其他操作为辅的策略来编写本篇文章。希望对你能有所帮助。

本文链接:http://blog.csdn.net/lemon_tree12138/article/details/50366993 -- Coding-Naga
                                                                 --转载请注明出处


基本操作:

1.插入

public void insert(int _value) {
        Node node = root;
        
        boolean inserted = false;
        while(!inserted) {
            if (_value == node.getValue()) {
                inserted = true;
            } else if (_value < node.getValue()) {
                Node leftNode = node.getLeft();
                if (leftNode == null) {
                    leftNode = new Node(_value);
                    node.setLeft(leftNode);
                    inserted = true;
                } else {
                    node = leftNode;
                }
            }  else {
                Node rightNode = node.getRight();
                if (rightNode == null) {
                    rightNode = new Node(_value);
                    node.setRight(rightNode);
                    inserted = true;
                } else {
                    node = rightNode;
                }
            }
        }
    }

2.查找

  这里就拿找到一个待删除节点为例作说明。

private Node[] searchRemoveNode(int _value) {
        Node parentNode = null;
        Node removeNode = root;
        
        while(removeNode != null) {
            if (removeNode.getValue() == _value) {
                break;
            }
            
            if (removeNode.getValue() < _value) {
                parentNode = removeNode;
                removeNode = removeNode.getRight();
            }
            
            if (removeNode.getValue() > _value) {
                parentNode = removeNode;
                removeNode = removeNode.getLeft();
            }
        }
        
        return new Node[]{parentNode, removeNode};
    }

3.删除

  嗯,重点来了。

  关于二叉搜索树的删除是相对比较麻烦的。这是为什么呢?我们知道二叉搜索可以快速查找某一个元素是否存在的原因,是BST遵循了一些规则。而我们麻烦的原因也正因为这个规则。

  或许你会说,删除有什么难的。直接记录一下待删除节点的左、右孩子节点,再遍历孩子节点并按之前的方式插入到BST中不就是可以了么?有什么难的?

  这是一个思路,但是不是太好,因为使用它我们总是会有一种提心吊胆的感觉。为什么?我们现在说明一种情况。比方说,我有一棵BST。它的待删除节点是10000,左右孩子节点都有9999个节点。那么是不是就是说我们还要再把这9999 * 2个节点再插入到BST中呢?而且插入过程中还有对树的遍历。

  说明上面那么太过生硬的方法之后,现在我就来说一个软一点的方法。我们先来看下面的三张图:


图-1 删除一个无子节点的节点


图-2 删除只有一个子节点的节点


图-3 删除有两个子节点的节点


  从上面的三张图我们就可以看出,要删除BST中的一个节点是要分情况讨论的。在第一种情况中,没什么好说的,就是直接删除就OK。代码如下:

private void removeNodeNoChild(Node parentNode, Node removeNode) {
        if (parentNode.getValue() == removeNode.getValue()) {
            return;
        } else if (parentNode.getValue() < removeNode.getValue()) {
            parentNode.setRight(null);
        } else {
            parentNode.setLeft(null);
        }
    }
  在第二种方法中,我要删除节点80。不过这个时候不能直接删除,因为待删除节点有一个子节点。我们把这个子节点挂到节点80的话父节点上就可以了。代码如下:

private void removeNodeOneChild(Node parentNode, Node removeNode) {
        if (parentNode.getValue() ==  removeNode.getValue()) {
            return;
        }
        
        if (removeNode.getValue() < parentNode.getValue()) {
            // 父节点的左孩子
            parentNode.setLeft(removeNode.getLeft() == null ? removeNode.getRight() : removeNode.getLeft());
        } else {
            // 父节点的右孩子
            parentNode.setRight(removeNode.getLeft() == null ? removeNode.getRight() : removeNode.getLeft());
        }
    }
  第三种情况就复杂一些。因为我们既不能直接删除,也不能把节点30的子节点挂到节点30的父节点20上面(因为每个节点的右孩子只能有一个,而节点30有两个孩子)。

  我们的做法是找到待删除节点(节点30)左孩子中最大的节点,这里我们打到了节点27。再把节点27来替换掉要删除的节点30。这样既快捷高效又保证不破坏BST的规则结构。代码如下:

private void removeNodeTwoChild(Node parentNode, Node removeNode) {
        if (parentNode.getValue() ==  removeNode.getValue()) {
            return;
        }
        
        Node maxValueNode = maxValueNode(removeNode.getLeft());
        
        if (removeNode.getValue() < parentNode.getValue()) {
            // 父节点的左孩子
            parentNode.setLeft(maxValueNode);
        } else {
            // 父节点的右孩子
            parentNode.setRight(maxValueNode);
        }
        
        maxValueNode.setLeft(removeNode.getLeft());
        maxValueNode.setRight(removeNode.getRight());
    }

Demo源码下载:

https://github.com/William-Hai/Binary-Sort-Tree

转载于:https://www.cnblogs.com/fengju/p/6336024.html

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值