1. 程式人生 > 其它 >二叉排序樹節點刪除詳解

二叉排序樹節點刪除詳解

二叉排序樹節點刪除詳解

摘要:本篇筆記作為補充筆記,主要講解在二叉排序樹中的節點刪除這一行為的操作

目錄

1.為何要重點探究二叉排序樹中的節點刪除?

  二叉排序樹不是普通的樹,在二叉排序樹中節點之間是有序的,因此在二叉排序樹中直接對節點進行修改是不被允許的,如果我們能夠恣意修改二叉排序樹中的值,那這棵樹很可能會亂套,因此我們必須規範在二叉排序樹中的修改行為,我們通常在二叉排序樹中不設定修改的方法,而是設定一個按值查詢並刪除的方法,接下來我們就重點介紹一下二叉排序樹中的刪除方法。

2.二叉排序樹中的幾種節點的刪除

2.1.葉子節點的刪除

  如果刪除的目標是一個葉子節點,那麼事情就簡單了,因為葉子節點沒有子樹,所以葉子節點的刪除就是簡單的刪除,把它刪了,完全不會影響到整棵樹的平衡性,因此理論上將葉子節點的刪除最為簡單,那麼接下來讓我們理一下葉子節點的刪除步驟:

1.找到要刪除的節點,我們將其命名為targeNode
2.找到要刪除的節點的父節點,我們命名為parent
3.判斷targeNode節點是parent節點的左子節點還是右子節點
4.根據第三步的結果將其parent的左孩子或者右孩子置為null,從而刪除目標節點,若是左子節點:parent.left = null;若是右子節點:parent.reight = null
2.2.非葉子節點的刪除(只有一個孩子節點)

  只有一個孩子節點的非葉子節點的刪除,需要考慮的問題就多了一些,我們需要考慮到將這個目標節點刪除之後,其孩子節點何去何從,我們不能像處理葉子節點一樣直接將其父節點的某個孩子節點置空了,而是需要讓它的孩子節點接在父節點上,如圖所示:

  我們需要先獲取到將要被刪除的節點所擁有的那棵子樹的根節點,如上圖所示,我們需要獲得其左子樹的根節點,之後,由於將要被刪除的節點是其父節點的左子樹,因此以它為根節點的這棵子樹,一定是全都小於它父節點的,因此這個將要被刪除的節點的子樹,也一定是要被接在其父節點的左邊的,如果不像上圖那樣,這個將要被刪除的節點位於其父節點的右側,則說明其所在子樹的所有值都大於父節點,那麼我們就將其唯一的那個子樹根節點接在父節點的右側,這個邏輯過程仍然不難理解,接下來我們寫出步驟:

1.找到要刪除的節點,我們命名為targeNode
2.找到刪除節點的父節點,我們命名為parent
3.找到要刪除節點的唯一子樹的根節點,這個節點可能是將被刪除的節點的左孩子節點或者右孩子節點,但由於它是唯一的,所以我們找到之後直接命名為child
4.判斷targeNode是其父節點parent的左子節點還是右子節點,如果是左子節點:parent.left = target.child; 如果是右子節點:parent.right = target.child
2.3.非葉子節點的刪除(有兩個孩子節點)

  這個情況看上去比較複雜,實際上操作起來並不困難,使用下面的方法,甚至都不用刪除指定節點,只需按照規則修改其中的值即可:

1.找到將被刪除節點的左子樹中的最大值
2.將這個最大值儲存,並刪除這個節點
3.將我們儲存到的左子樹最大值替換給將被刪除的節點的值

  或者我們可以使用右子樹:

1.找到將被刪除節點的右子樹中的最小值
2.將這個最小值儲存,並刪除這個節點
3.將我們儲存的右子樹的最小值替換給將被刪除節點的值

  這兩個方法思路一樣,只不過是方向不同,如下圖,我們使用更直觀的圖片來展示這個過程:

   如圖所示,我們先找到了將被刪除的節點的右子樹中的最小值,然後將其放在了將被刪除的節點的值上,之後刪除那個右子樹上最小值的節點即可,其原理並不複雜,這是因為一顆二叉排序樹的根節點,肯定是小於右子樹上所有值,且大於左子樹上所有值的,因此我們選用右子樹上的最小值,替換根節點,仍然能滿足這個條件,因為右子樹上的最小值肯定大於其他值,並且一定大於左子樹上的所有值,因此我們可使用右子樹上的最小值進行替換,同理我們也可以使用左子樹上的最大值進行替換,需要注意的是,右子樹上的最小值和左子樹上的最大值,要麼是根節點,要麼是一個僅有一棵子樹的節點,在尋找左子樹中的最大值時,我們只需要一股腦的往右找;在尋找右子樹中的最小值時,我們則需要一股腦的往左找即可。

2.4.根節點的刪除

  當我們刪除的節點是根節點時,我們需要先根據其parent來確認一下將要刪除的節點是否時根節點,如果它是根節點,那麼它的parent將是null,因此只要我們得到了一個parent值,其為null的話,那麼我嗯將要刪除的節點就是根節點,當樹中只有一個節點的時候,也就是根節點就是葉子節點的時候我,我們僅需要將root置為null即可,如果當前根節點只有一個子樹,我們將其子樹的根節點賦予給root即可(root是當前結構內的根指標,是管理類中的欄位),而根節點有兩個節點的時候,使用以上演算法並沒有什麼影響,因為根欄位的指向並沒有變化,變化的是值,而被刪除的節點時另外的節點,時右子樹中值最小的節點,或者左子樹中值最大的節點。