使用javascript實現排序二叉樹(2)

JinsongChai發表於2018-08-28

使用javascript實現排序二叉樹(2)

上一篇文章我們構造了基本的一個排序二叉樹的資料結構,但是僅僅是定義了一個insert方法去建立二叉排序樹,今天我們來給我們的資料結構新增一些遍歷的功能。

二叉樹的三種遍歷方式(以根節點為準來定義前、中、後)的介紹及其應用場景:

  1. 前序遍歷

    • 順序:根節點 => 左子樹 => 右子樹
    • 應用:可以用來構建檔案的目錄結構,輸出所有目錄並分層
  2. 中序遍歷

    • 順序:左子樹 => 根節點 => 右子樹
    • 應用:可以進行排序,輸出的結果是一個遞增的序列
  3. 後續遍歷

    • 順序:左子樹 => 右子樹 => 根節點
    • 應用:後續遍歷是先遍歷子樹,最後到根節點,可以實現統計節點數、計算資料夾大小的功能

思考

  1. 遍歷的方法是給誰用的,是否需要暴露出去
  2. 如果暴露出去,怎樣設計才能讓呼叫者能夠獲取到每一個節點並且進行對應的操作

結論

  1. 肯定是要暴露出去給別人呼叫的
  2. 給別人呼叫,具體的邏輯是不確定的,所以應該是呼叫者傳入一個函式,我們在遍歷的時候把每一次的節點都傳給這個函式,並且去呼叫這個函式,這樣我們不用管具體函式的邏輯,反正已經把它想要的 節點 給他了,具體怎樣操作我們不用管。

分析完畢之後,依然是上次的程式碼,我們給他新增前序中序和後續遍歷的方法:


function BinaryTree(){
  var root = null; //根節點預設為null
  //節點型別的建構函式
  function Node(key){
    this.key = key;
    this.left = null;
    this.right = null;
  }
  //插入方法
  this.insert = function(key){     
    var newNode = new Node(key);
    if(root === null){
       root = newNode;
    }else{
       insertNode(root,newNode)
    }
  }
  var insertNode = function(node,newNode){
    if(newNode.key < node.key){
      if(node.left === null){
         node.left = newNode;
      }else{
         insertNode(node.left,newNode)
      }
    }else{
      if(newNode.key > node.key){
        if(node.right === null){
          node.right = newNode;
        }else{
          insertNode(node.right,newNode)
        }
      }
    }
  }
  
  /*--------------------------------------------------------*/
  /*
      前序遍歷: 根節點 => 左子樹 => 右子樹
  */
  this.preTravel = function(callback){
    //和上面插入操作類似,都用一個內部的函式來實現具體的邏輯,因為需要使用root
     preTravelNode(root,callback); 
  }   
  /* 
      邏輯:
          1. 判斷傳入的節點是否為null,如果為null就直接return
          2. 如果不為null,則繼續對該節點下的left和right進行遞迴呼叫
          3. 具體的呼叫順序根據為 根節點 => 左子樹 => 右子樹
  */
  function preTravelNode(node,callback){
    if(node !== null){ 
       callback(node.key); 
       preTravelNode(node.left,callback);
       preTravelNode(node.right,callback);
    }
  }
  
  //中序遍歷
  this.middleTravel = function(callback){
    middleTravelNode(root,callback);
  }
  function middleTravelNode(node,callback){
    if(node !== null){
       middleTravelNode(node.left,callback);
       callback(node.key);
       middleTravelNode(node.right,callback);
    }
  }
  
  //後續遍歷
  this.nextTravel = function(callback){
    nextTravelNode(root,callback);
  }
  function nextTravelNode(node,callback){
    if(node !== null){
       nextTravelNode(node.left,callback);
       nextTravelNode(node.right,callback);
       callback(node.key);
    }
  }
}

var nodes = [8,7,3,4,6,5,2,9,12]
var binaryTree = new BinaryTree();
nodes.forEach((item)=>{
    binaryTree.insert(item)
})
//測試前序遍歷
binaryTree.beforeTravel((key)=>{
  console.log(key) // 8,7,3,2,4,6,5,9,10
})
console.log('--------------------')
//中序遍歷
binaryTree.middleTravel((key)=>{
  console.log(key) // 2,3,4,5,6,7,8,9,10
})
console.log('--------------------')
//後續遍歷
binaryTree.nextTravel((key)=>{
  console.log(key) // 2,5,6,4,3,7,10,9,8
})

具體的邏輯

  1. 判斷傳入的節點是否為null,如果為null就直接return
  2. 如果不為null,則繼續對該節點下的left和right進行遞迴呼叫
  3. 具體的呼叫順序根據前序、中序、後序、的訪問節點順序去修改呼叫的順序

還是放上這個二叉樹的圖,根據圖去對比測試的遍歷結果更直觀:

二叉樹圖

重點

  1. 怎樣設計遍歷方法,呼叫者傳什麼東西進來,我們要暴露什麼東西出去,這個地方得想明白

下期內容

  1. 實現二叉樹的節點查詢功能
  2. 實現二叉樹中節點的刪除功能
  3. 實現一個二叉樹的一個小遊戲

上期內容

  1. 使用javascript定義一個排序二叉樹

相關文章