javascript中的二叉樹一(binary tree)
畢業也快2年了,畢業之後就沒有認真寫過部落格了,都是那裡學習一下,這裡弄一下。學習了也不做筆記,過後就忘記了。我對這種狀態打從心裡是討厭的。
進入正題,今天的筆記是記錄javascript二叉樹的學習,是非常基本的知識加上一些自己的認識。適合想了解javascript二叉樹的萌新,大神請繞路走,當然如果發現有什麼理解上的錯誤,還望不吝賜教。
===================漂亮的分割線===================
首先說下我對二叉樹的理解:
1,二叉樹是由一系列有規則的節點構成
2,二叉樹每一個節點可以看成為物件,必有key(節點值),可以有left(節點),right(節點)這三個屬性
3,每個節點的left節點的key必定小於當前key值
4,每個節點的right節點的key必定大於當前的key值
那麼假如我們要把一個陣列構成二叉樹,需要哪些程式碼?很簡單,記住上面的幾點,我們來一步一步把陣列變成二叉樹形式
一,
1,二叉樹是由一系列有規則的節點構成,
2,二叉樹每一個節點可以看成為物件,必有key(節點值),可以有left(節點),right(節點)這三個屬性
思考: 陣列的每一個值將變成二叉樹的節點(先不管這個節點怎麼排序),那麼我們在迴圈陣列的時候,是不是都要處理下?
答: 我定義下面一個類,到時候就可以依次例項化為節點了。看下好不好理解...
//節點類 class Node { constructor(key) { this.left = null this.right = null this.key = key } }
進一步解釋: 當迴圈陣列的時候,就可以把每一個陣列項,例項化為節點,類似這樣new Node(陣列Item)
二,
3,每個節點的left節點的key必定小於當前key值
4,每個節點的right節點的key必定大於當前的key值
這2點是生成二叉樹的規則。那我們是不是應該有一個二叉樹類呢?
//二叉樹類 class BinaryTree{ }
思考: 二叉樹類要哪些東西呢?補充類看下是不是應該這些
//二叉樹類 class BinaryTree { constructor() { this.root = null //二叉樹根節點 } insert (key) { //插入節點的方法 } }
解釋: 每一個二叉樹例項應該都有一個根節點,然後暴露一個可以插入節點的方法(先不管插入規則,後續講解)
接下來就是重點了: 如何實現插入邏輯能實現上面3,4兩點規則呢?
第一點:我們要確定一個根節點,然後在根節點基礎上實現二分法
完善insert方法如下:
class BinaryTree { constructor() { this.root = null } insert (key) { const newNode = new Node(key) // 這裡也可以在陣列那裡執行,但這裡可以避免多次例項操作 if (this.root === null) { this.root = newNode } else { this.inOrderTraversNode(this.root, newNode) } } inOrderTraversNode (node, newNode) { } }
解釋:當呼叫insert方法的時候都先確定root的值,然後在根節點為入口進行二分。inOrderTraversNode方法就負責二分法。
思考: inOrderTraversNode方法怎麼樣實現二分法?
答: 該方法為一個遞迴方法。功能為:有2個引數,一個是當前已經存在的節點,後一個是要插入的新節點,就是把新節點插入到當前節點的正確的(左節點或者右節點)位置。
比如:當根節點確定之後,呼叫該方法插入一個新左節點,此時形成了2個節點的二叉樹。此時若又一個左節點需要插入,我們就能可以遞迴呼叫該方法實現了。
//二叉樹類 class BinaryTree { constructor() { this.root = null } insert (key) { const newNode = new Node(key) if (this.root === null) { this.root = newNode } else { this.inOrderTraversNode(this.root, newNode) } } inOrderTraversNode (node, newNode) { if (newNode.key < node.key) { // 左插 if (node.left === null) { node.left = newNode }else{ this.inOrderTraversNode(node.left, newNode) } } else { // 右插 if (node.right === null) { node.right = newNode } else { this.inOrderTraversNode(node.right, newNode) } } } }
所有程式碼在這裡,可以好好理解下
const node = [8, 1, 3, 10, 12, 6, 13, 15, 18, 7] //節點類 class Node { constructor(key) { this.left = null this.right = null this.key = key } } //二叉樹類 class BinaryTree { constructor() { this.root = null } insert (key) { const newNode = new Node(key) if (this.root === null) { this.root = newNode } else { this.inOrderTraversNode(this.root, newNode) } } inOrderTraversNode (node, newNode) { if (newNode.key < node.key) { // 左插 if (node.left === null) { node.left = newNode }else{ this.inOrderTraversNode(node.left, newNode) } } else { // 右插 if (node.right === null) { node.right = newNode } else { this.inOrderTraversNode(node.right, newNode) } } } } const binaryTree = new BinaryTree() node.map(function(item) { binaryTree.insert(item) }) console.log(binaryTree.root)