这是我参与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
查找当前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;
}
}
复制代码
这种状况也要分红两种状况考虑,这个子节点多是左子节点,也多是右子节点;不过这两种状况的思路是相同的,分别进行处理就行了;下面说要删除的节点有一个左子节点的状况,右侧同理.code
判断是否为根节点orm
无论是在哪一种状况,都要记得首先要判断这个要删除的节点是否是根节点;由于若是是根节点的话,与其余节点位置的处理方式是不相同的。若是是根节点,直接从新让这个要删除的子节点为根节点便可;get
判断要删除的节点在其父节点的左侧仍是右侧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
}
}
复制代码
这种状况是最复杂的....(想一想就很复杂)这种状况也分为多种状况,无论在哪种状况中,咱们都须要在删除节点current
的子节点中找一个代替它的节点,并且这个替代它的节点要跟current
节点最接近;那么要怎么样才是最接近的呢?
那就是current
左子树中的最大值,以及current
右子树的最小值,也就是要往current
左子树的最右边进行查找直到这个节点指向为空,或者往current
的右子树的最左边进行查找直到这个节点指向为空;此时找到的这个节点就是能够替代current
节点。
好比说下面这一张图,若是要删除15这个节点,能够找14或者18来代替它;
前驱&后继:比current
小一点点的节点称为current
节点的前驱;比current
大一点点的节点称为current
节点的后继;也就是说,在咱们要是删除current
的是否,就是要找到它的前驱或者后继;
下面用以找后继为例子:
首先要找后继
经过循环来查找它的后继,这个后继多是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;
复制代码
把原来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;
复制代码