動畫 | 什么是二分搜索樹(二叉查找樹)?


二分搜索樹屬性

二分搜索樹的又名比較多,有的叫二叉排序樹,也有的叫二叉查找樹,或者有序二叉查找樹。是指一棵空樹或者具有下列性質的二叉樹:

1.若任意節點的左子樹不空,則左子樹所有節點的值均小於它根節點的值;

2.若任意節點的右子樹不空,則右子樹所有節點的值均小於它根節點的值;

3.任意節點的左、右子樹也分別為二叉查找樹;

4.沒有鍵值相等的節點。

它的查找、插入和刪除的時間復雜度都等於樹高,期望值是O(logn),最壞時間復雜度是O(n),比如樹退化成線性表。

(響應讀者的建議,視頻動畫不放BGM了)

查找元素

二分搜索樹是為了實現快速查找而生的,也支持快速添加和刪除一個數據。如何查找某個元素首先跟根節點去做比較,如果相等的話就返回;如果待查元素要比根節點小,就進行左子樹遞歸查找;如果待查元素要比根節點大,就進行右子樹的遞歸查找;如果查找到最后還沒有一個符合的元素,就返回null。

遞歸查找

遞歸查找的方式有很多,有層序遍歷、前序遍歷、中序遍歷和后序遍歷。我這里就舉后面三個遍歷方式。

Code

如果代碼是下面這樣寫的,那它遍歷過程是怎么樣的?看下面視頻動畫。

視頻動畫:前序遍歷

視頻動畫:前中后遍歷

視頻動畫:前中后遍歷 前序

視頻動畫:前中后遍歷 中序

經過中序遍歷得到的正好是一個升序序列。

視頻動畫:前中后遍歷 后序

如果不考慮升序,后序遍歷能夠為二分搜索樹早點釋放內存。

添加元素

對於二叉樹的添加和刪除元素,使用鏈表存儲形式比較好操作的,如果使用數組形式存儲,刪除某一個有子樹的元素會引發一系列的位置改變,涉及到交換元素的位置,性能也比鏈表的小。所以待會后面出現的偽代碼都以鏈表存儲形式去操作。

視頻動畫:添加元素

Code

刪除元素:刪除最小和最大的元素

刪除最小和最大的元素很簡單,如果是刪除最小的元素,從二叉樹的頂點出發,一直遞歸它的左孩子,直到某節點的左孩子為空,這時候這個節點就是最小的元素。刪除最大的元素也是一樣的,一直遞歸它的右孩子,直到某節點的右孩子為空。

視頻動畫:刪除最小和最大的元素

刪除任意元素

如果刪除任意元素,而這元素正好有左右子樹的,那該是怎么般呢?

1962年,Hibbard提出了Hibbard Deletion的解決方法。

看到Hibbard名字就想起來,我在希爾排序介紹過Hibbard增量序列,也把它相應的公式通過代碼體現出來,代替希爾增量序列去進行希爾排序,最壞時間復雜度也比希爾增量序列的要小。

回到刪除有左右子樹的元素,想想它的左右子樹也屬於二叉排序樹(也是二分搜索樹),它左子樹的最大值比它小,它右子樹的最小值比它大。所以不管選擇左子樹的最大值還是選擇右子樹的最小值,替換掉要刪除的元素,整個二叉樹都是符合二分搜索樹的規則。

視頻動畫:刪除任意元素

Code

支持重復元素的二分搜索樹

二分搜索樹有一個規則是:沒有鍵值相等的節點。那么就不建議把待添加的元素跳過值相等的節點,到下一步繼續比較直到插入新的節點。比如我想插入23,插完之后上有23,下有23,那查找就沒有意義了,也破壞了時間復雜度上的O(logn)。

建議就是在節點上加一個屬性:count。當插入23的時候,count就可以自算++。這不僅滿足了沒有鍵值相等的規則,也滿足時間復雜度的期望值。

Code


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM