二叉樹《學習筆記》——刪除操做

這是我參與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;
    複製代碼
相關文章
相關標籤/搜索