二叉树《学习笔记》——删除操做

这是我参与8月更文挑战的第9天,活动详情查看:8月更文挑战markdown

删除二叉树的子节点

这个比较复杂一点,要分状况进行处理。首先找到要删除的节点,没找到就不用删除了;处理方式以下:post

首先定义一些临时的变量,将查找的key和当前结点的key值进行比较,若是较小就往左子树进行查找,若是较大就往右子树进行查找,而后再经过循环来找要删除的节点;ui

var current = this.root;
 var parent = null;
 var isLeftChild = true
 while (current.key != key) {
     parent = current;
     if (key < current.key) {
         isLeftChild = true;
         current = current.left;
     } else {
         isLeftChild = false;
         current = current.right;
     }
     if (current == null) return false;
 }
复制代码

找到后一共有三种状况:this

1、删除叶子节点

查找当前current节点的left和right是否为空,且不是根节点,直接让它们指向null便可;若是是根节点的话,那么就至关于清空二叉树。spa

if (current.left == null && current.right == null) {
    if (current == this.root) {
        this.root = null;
    } else if (isLeftChild) {
        parent.left = null;
    } else {
        parent.right = null;
    }
}
复制代码

2、删除只有一个子节点的节点

这种状况也要分红两种状况考虑,这个子节点多是左子节点,也多是右子节点;不过这两种状况的思路是相同的,分别进行处理就行了;下面说要删除的节点有一个左子节点的状况,右侧同理.code

  1. 判断是否为根节点orm

    无论是在哪一种状况,都要记得首先要判断这个要删除的节点是否是根节点;由于若是是根节点的话,与其余节点位置的处理方式是不相同的。若是是根节点,直接从新让这个要删除的子节点为根节点便可;get

  2. 判断要删除的节点在其父节点的左侧仍是右侧it

    该删除节点为左节点或右节点也影响了要将其子节点放在父节点的位置,若是当前节点是其父节点的左子节点,那么就要将当前节点的子节点连到其父节点的左子节点上;右侧同理.io

if (current.right == null) {
    if (current == this.root) {
        this.root = current.left;
    } else if (isLeftChild) {
        parent.left = current.left;
    } else {
        parent.right = current.left
    }
}
复制代码

3、删除有两个子节点的节点

这种状况是最复杂的....(想一想就很复杂)这种状况也分为多种状况,无论在哪种状况中,咱们都须要在删除节点current的子节点中找一个代替它的节点,并且这个替代它的节点要跟current节点最接近;那么要怎么样才是最接近的呢?

那就是current左子树中的最大值,以及current右子树的最小值,也就是要往current左子树的最右边进行查找直到这个节点指向为空,或者往current的右子树的最左边进行查找直到这个节点指向为空;此时找到的这个节点就是能够替代current节点。

好比说下面这一张图,若是要删除15这个节点,能够找14或者18来代替它;

二叉搜索树.png

前驱&后继:比current小一点点的节点称为current节点的前驱;比current大一点点的节点称为current节点的后继;也就是说,在咱们要是删除current的是否,就是要找到它的前驱或者后继;

下面用以找后继为例子:

  1. 首先要找后继

    经过循环来查找它的后继,这个后继多是current的儿子,也可能隔了好几代,若是是隔了好几代的话,在替代的时候就要让这个后继节点指向原来current节点的右子树;

    而且,若是这个后继节点还有儿子的话,也要让这个后继节点的父节点指向这个后继节点的子节点;就好比上面的图中,让18这个节点替代20的时候,不只要让18指向20的子树,同时也要让20指向18的子节点19;

    var successor = delNode;
    var current = delNode.right;
    var successorParent = delNode;
    while (current != null) {
        successorParent = successor;
        successor = current;
        current = current.left
    }
    // 3. 判断寻找的后继节点是否为delNode的right节点
    if (successor != delNode.right) {
        successorParent.left = successor.right;
        successor.right = delNode.right
    }
    return successor;
    复制代码
  2. 把原来current的父节点和左子树给后继节点successor

    首先也要判断这个节点是否是根节点,是的话就直接让根节点指向这个后继节点successor;不是的话就判断此时current是位于左子树的位置仍是右子树,让current的父节点指向successor;再让把current的左子树赋值给给successor

    if (current == this.root) {
        this.root = successor;
    } else if (isLeftChild) {
        parent.left = successor;
    } else {
        parent.right = successor;
    }
    successor.left = current.left;
    复制代码
相关文章
相关标签/搜索