1. 程式人生 > >實現排序二叉樹

實現排序二叉樹

eno -type lis blank 後者 升序 以及 代碼 細節

概念

二叉樹:如圖。

  • 某個節點最多有兩個子節點的樹。常用於排序。效率較高。
  • 節點中的值:鍵。key。
  • 兄弟節點:擁有同一個父節點的節點。
  • 根節點:沒有父節點
  • 外部節點:葉子節點,沒有子節點。
  • 內部節點:中間節點。有子節點。
  • 高:節點都有深度,最大的節點深度即為這棵樹的高。
  • 排序二叉樹:節點左孩子的值小於它,右孩子的值大於它。顯然,左子樹的節點值都比當前節點小,右子樹的逗比當前節點大。

技術分享

代碼實現

需要創建對象實現其基本結構、封裝相應屬性和方法。創建對象或者繼承對象的方法可見《JavaScript高級程序設計》第六章。這次實現則采取了構造函數進行封裝的方法。

結構

  • 完整的排序二叉樹,包括對節點(特別地,根節點)結構的描述、以及必要的方法。
  • 節點的一般結構:
    var Node = function(key){
        this.key = key;
        this.left = null;
        this.right = null;
    };
    
    var root = null;
  • 實際上是個也是個節點的構造函數,將在之後的insert()方法中對其進行調用。

方法

  • 有了基本的節點結構,就可以在此基礎上使用必要的方法來創建、遍歷、查詢、刪除排序二叉樹了。
  • 創建一棵排序二叉樹:insert(key)方法
    1. 基本描述:顯然需要一個一個的插入相應的節點值,最後循環得到完整的排序二叉樹。
    2. 分析:需要通過遞歸依次將待插入的節點與排序二叉樹的部分節點進行大小比較。從根節點開始,遵循左子節點小於當前節點,右子節點大於當前節點的規則。就是說,需要考慮兩種情況:插入根節點、插入一般節點。
    3. 借助:insertNode(key)函數。
    4. 遞歸:如圖(借助中序遍歷進行說明)。遞歸函數有個進棧和退棧的過程。當本次遞歸中所有語句執行完畢(這是一般情況,函數執行完畢都會默認return)或者遇到return語句的時候,會返回上一個調用這次遞歸的位置。並從該位置開始繼續執行接下來的語句。
      技術分享
  • 遍歷二叉樹:
    • 同樣涉及遞歸。
    • 操作的對象是整棵樹
    • 顯然x序遍歷的“x”是前/中/後取決於當前節點的位置,而左一直在右前面
    • 中序遍歷:
      1. 遍歷順序:左子節點(樹)->當前節點->右子節點(樹);
      2. 適合進行升序打印。
      3. 方法:inOrderTraverse(callback);//從根節點開始,callback()就是處理遍歷到的節點的方法,較靈活。借助inOrderTraverseNode(node,callback)函數
    • 前序遍歷:
      1. 遍歷順序:當前節點->左子節點(樹)->右子節點(樹);
      2. 適合進行排序二叉樹的復制,效率比創建一棵同樣的二叉樹高;
      3. 方法:preOrderTraverse(callback);//從根節點開始,callback()就是處理遍歷到的節點的方法,較靈活。借助preOrderTraverseNode(node,callback)函數
    • 後序遍歷:
      1. 遍歷順序左子節點(樹)->右子節點(樹)->當前節點;
      2. 適合進行文件系統的遍歷。
      3. 方法:postOrderTraverse(callback);//從根節點開始,callback()就是處理遍歷到的節點的方法,較靈活。借助postOrderTraverseNode(node,callback)方法。
  • 查找二叉樹
    • 查找是否有符合條件的節點。
    • 同樣涉及遍歷。
    • 查找整棵二叉樹的最小值:從根節點開始,不斷查找左子節點,直到某一個左子節點是葉節點,即為最小值對應的節點。
    • 查找整棵二叉樹的最大值:從根節點開始,不斷向右子節點查找,直到某一個右子節點是葉節點,即為最大值對應的節點
    • 查找任意值輸入值:
      1. 與當前節點比較大小:若相同返回這個值;若小於當前節點,則進入左子樹;若大於當前節點,則進入右子樹。。。
      2. 直至找到相同值 or 無法繼續查找(沒有左節點或者右節點了),前者表示二叉樹中存在相應節點(可以返回true或其他操作);後者表示不存在相應節點(可以返回false或進行其他操作)
      3. search(key)方法,借助search(node,key)函數。一般從根節點開始查找。
  • 刪除節點(比較重要)
    • 同樣涉及遍歷
    • 有以下對應情況需要進行處理:
      1. 若只有一個子節點(只有左節點or右節點):刪除該節點,將其父節點與其子節點連接起來。
      2. 若沒有子節點(葉子節點):刪除該節點,且刪除其父節點指向他的連接(=null)
      3. 若有兩個子節點:從右子樹中找到值最小的那個,用其代替刪除的節點。當然需要註意處理一些細節問題。比如幾處指針的指向。
    • remove(key)方法。借助removeNode(node,key)函數。同樣一般從根節點開始。
    • 其實涉及到節點的查找。

其他鏈接

  • GitHub:實現排序二叉樹
  • 基於排序二叉樹的簡單遊戲

實現排序二叉樹