這是我參與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;
複製代碼