上一篇文章咱們講解了二叉樹的基礎知識,什麼是二叉樹、二叉樹的特色、二叉樹的存儲方式、二叉樹的遍歷等。基礎歸基礎,理論歸理論。最重要的最終還要和實踐掛鉤。前端
今天這篇主要分享一下二叉樹的一些簡單應用,二叉樹涉及到的不少應用也是有難度的,好比紅黑樹、AVL 樹、B+樹等,這節不會涉及到。還須要自行深刻探索。本篇但願可以給你帶來二叉樹的應用思考。編程
咱們都知道上一節分享到了二叉樹的遍歷,那麼二叉樹還能幹什麼,數據結構之因此爲數據結構,對數據進行操做的,查找、刪除、插入等,那麼二叉樹對於這些操做是否更高效呢?數組
二叉樹中可以實現快速插入、刪除、查找的特殊二叉樹就是二叉查找樹了。前邊咱們講了數組、鏈表、二分查找等,之後的文章還會有哈希表、跳錶等也是用於數據的插入、查找等,那麼二叉查找樹又有哪些優點呢?網絡
那什麼是二叉查找樹?爲什麼實現快速的插入、刪除操做?有了上一篇文章的基礎,都是爲這篇的二叉查找樹作鋪墊。二叉查找樹的由來都是由二叉樹的特色決定的。數據結構
可是二叉查找樹又對其進行改進,要求在二叉查找樹中左子節點必須小於根節點,而右子節點則大於根節點,這種特殊的二叉樹就叫作二叉查找樹。性能
二叉查找樹的定義很是簡單,那麼下面咱們就見識見識二叉查找樹的各類操做。學習
二叉查找樹如何插入一個節點元素?由於們知道二叉查找樹的特色,左子節點小於根節點右子節點大於根節點。插入一個元素,首先讓該元素和根節點比較,若是小於根節點,就插入到左子節點位置,若是左子節點有數據,就繼續和插入的數據比較大小,直到當前結點爲葉子節點位置 —— 整個過程也是一個遞歸的過程。優化
動畫實現:動畫
性能分析:
插入操做的時間複雜度跟整棵樹的高度成正比,時間複雜度爲 0(log2n)。
代碼實現: JavaScript 版本
Java 版本
查找一個節點元素一樣也是根據二叉查找樹的特色進行查找,首先和根節點進行比較大小,小於根節點就在左子節點進行遞歸,不然在右子節點進行遞歸查找。若是查找到該元素與某節點相同,則能夠返回該節點,不然繼續遞歸直到查找完畢沒有查找到。
動畫實現:
性能分析:
查找的時間複雜度一樣和二叉查找樹的高度成正比,爲 O(log2n)。
代碼實現: JavaScript 版本
Java 版本
對於刪除,咱們想想,會多多少少涉及一些邊界條件。好比,二叉查找樹只有一個根節點或者刪除二叉查找樹的葉子節點以及中間結點,咱們寫代碼的時候要作的就是分別判斷這幾種狀況,而後進行一一處理,這樣說,邏輯聽起來更清晰一點。
狀況一:若是咱們要刪除樹中的節點沒有子節點,也就是說咱們刪除的節點爲葉子節點的話,咱們直接將葉子節點的父節點指向刪除節點的指針設置爲 null。
動畫實現:
性能分析:
刪除操做一樣也是如此,時間複雜度爲 O(log2n)。
狀況二:第二種狀況就是,若是刪除的節點下正好有一個節點(左子節點或者右子節點),直接將刪除節點的父節點直接指向該刪除節點的子節點。
動畫實現:
狀況三:若是刪除的節點下有兩個子節點就有點小複雜了,咱們先來看如何操做,而後再解釋緣由。先將找到刪除節點的右子樹中遞歸找到最小的節點元素,將其替換咱們要刪除的節點。
由於刪除節點的右子樹最小的節點也要比刪除節點的左子樹要大,並且最小節點沒有葉子節點,因此替換後仍是符合二叉查找樹的特色。
動畫實現:
代碼實現: JavaScript 版本
Java 版本
經過上邊二叉樹的三種操做,咱們作一個總結,爲何各類操做的不相同,都是朝着什麼方向去變化的?對了,不管是插入仍是查找、刪除,都是可以讓二叉查找樹變化後的結構還可以具有二叉查找樹的特色(左子節點小於根節點,右子節點大於根節點)。
以上咱們存儲的只是不重複的數據,若是咱們數據中有重複數據怎麼進行操做呢?
咱們有如下幾種方式進行優化,咱們能夠用數組和鏈表等動態的數據結構充當節點,這樣就能夠把重複的數據存儲到一個節點上。
還有一種策略就是咱們把重複的數據當作大於根節點處理,也就是存儲到右子樹上。
可是咱們的查找和刪除要優化下,若是查找一個元素,查找到了,可是須要繼續往下查找,由於可能存在重複的數據。刪除也是一樣的道理,刪除一個元素,刪除以後繼續查找是否還存在重複數據,而後對其重複數據進行刪除。
上邊咱們分別對二叉查找樹的插入、刪除、查找的時間效率進行了分析,也說了時間效率和樹的高度成正比,那麼問題來了,樹的高度如何求?
咱們運用咱們的數學功底算一下,咱們先算算一顆徹底二叉樹有多少的節點,第一層有1個,第二層2個,第三層,4 個,依次類推,第 n 層有多少就要用到等比數列,也就是 2 的n-1次方。
咱們粗略估算,讓等式等於 1 時,此時n = log2n+1,此時咱們的 n 表明是樹的第幾層,而後轉化爲高度就是h = log2n。
上邊咱們已經分析過,二叉查找樹的不管是插入仍是查找、刪除,都與樹的高度成正比,也就是log2n。
可是咱們要記住一個前提,咱們前邊分析的樹的高度是徹底二叉樹,若是不是徹底二叉樹,那麼時間複雜度就會發生改變,好比咱們一直插入的數據會致使整棵樹會失去平衡,退化成鏈表,時間複雜度就變成了O(n)。
那麼如何解決上邊的問題呢?咱們須要構建一棵平衡的二叉查找樹,每當節點之間快要失去平衡的時候,通過必定的策略,使其達到平衡的狀態,這樣就算在最壞的狀況下也不會退化成鏈表。好比,AVL 樹、紅黑樹,這些涉及到的比較難,咱們本篇不深刻了解。
今天咱們主要講了二叉樹中的一種特殊二叉樹,二叉查找樹又叫作二叉搜索樹。
二叉查找樹是根據自身的特色,左子節點小於根節點,右子節點大於根節點。從而達到可以實現動態的插入、刪除、查找操做,且操做的時間複雜度和樹的高度成正比。可是若是一直不平衡的插入,會致使出現二叉查找樹退化成鏈表的狀況,因此咱們更須要一種平衡的二叉查找樹。
文章+動畫寫了好幾個小時,不妨點贊支持一下。嘻嘻,你不點贊說明你很自私,你怕那麼好的文章讓別人也看到。開個小小玩笑。
能夠關注小鹿公衆號:「小鹿動畫學編程」,後臺回覆:「資源」。送你一份小鹿以前自學的資料和拉你進免費學習羣哦!
做者Info:
【做者】:小鹿
【原創公衆號】:小鹿動畫學編程。
【簡介】:和小鹿同窗一塊兒用動畫的方式從零基礎學編程,將 Web前端領域、數據結構與算法、網絡原理等通俗易懂的呈獻給小夥伴。先定個小目標,原創 1000 篇的動畫技術文章,和各位小夥伴共同努力一塊兒學習!公衆號回覆 「資料」 送一從零自學資料大禮包!
【轉載說明】:轉載請說明出處,謝謝合做!~