JavaScript 二叉樹算法排序 圖文並茂 這篇就夠了

二叉樹

在計算機科學中,二叉樹是每一個結點最多有兩個子樹的樹結構。一般子樹被稱做「左子樹」(left subtree)和「右子樹」(right subtree)。二叉樹常被用於實現二叉查找樹和二叉堆。 一棵深度爲k,且有2^k-1個節點的二叉樹,稱爲滿二叉樹。這種樹的特色是每一層上的節點數都是最大節點數。而在一棵二叉樹中,除最後一層外,若其他層都是滿的,而且最後一層或者是滿的,或者是在右邊缺乏連續若干節點,則此二叉樹爲徹底二叉樹。具備n個節點的徹底二叉樹的深度爲floor(log2n)+1。深度爲k的徹底二叉樹,至少有2k-1個葉子節點,至多有2k-1個節點。。node

  • 以上是書面解答 —— 下面我總結一下

結構

二叉樹結構

  • 二叉樹分爲 : 根節點 —— 中間節點 ——葉子節點
  1. 根節點是沒有子節點的
  2. 中間節點有子節點也有父節點
  3. 葉子節點只有父節點沒有子節點

執行方式

執行方式

  • 小於父節點的節點放在左邊 大於的放在右邊 以此類推 不斷的遞歸
function BinaryTree () {
                //建立對象
                class Node {
                    constructor (key) {
                        this.key = key
                        this.left = null
                        this.right = null
                    }
                }
                //初始化root
                let root = null
                
                const  insertNode =  (node, newNode) => {
                        if (newNode.key < node.key) {
                        if (node.left === null) {
                            node.left = newNode
                        } else {
                            insertNode(node.left, newNode)
                        }
                    } else {
                        if (node.right === null) {
                            node.right = newNode
                        } else {
                            insertNode(node.right, newNode)
                        }
                    }
                }


                    
                this.insert = (item) =>{
                    let newNode = new Node(item)
                    if (root === null) {//判斷是否有根節點
                        root = newNode
                    } else {
                        insertNode(root, newNode)//調用二叉處理方法
                    }
                }

                //中序排序
                const inOrderTraverseNode = (node, callback) => {
                    if (node !== null) {
                        inOrderTraverseNode(node.left, callback)
                        callback(node.key)
                        inOrderTraverseNode(node.right, callback)
                    }
                }

              

                //前序遍歷
                const preOrderTraverseNode = (node, callback) => {
                    if (node !== null) {
                        callback(node.key)
                        preOrderTraverseNode(node.left, callback)
                        preOrderTraverseNode(node.right, callback)
                    }
                }

                

                //後序遍歷
                const postOrderTraverseNode = (node, callback) => {
                    if (node !== null) {
                        postOrderTraverseNode(node.left, callback)
                        postOrderTraverseNode(node.right, callback)
                        callback(node.key)
                    }
                }

               

                this.allOrderTraverse = (callback, FuncName) => {//入口函數
                    switch (FuncName) {
                        case 'inOrderTraverseNode': inOrderTraverseNode(root, callback)
                            break
                        case 'preOrderTraverseNode': preOrderTraverseNode(root, callback)
                            break
                        case 'postOrderTraverseNode' : postOrderTraverseNode (root, callback)
                            break
                        default: alert('輸入錯誤,請輸入:inOrderTraverseNode,preOrderTraverseNode,postOrderTraverseNode 中的一種 ') 
                        break;
                    }
                }             

            }

            let nodes = [8, 3, 10, 1, 6, 14, 4, 7, 13]

            var BinaryTree = new BinaryTree()
            nodes.forEach(function (key) {
                BinaryTree.insert(key)
            })
            BinaryTree.allOrderTraverse(key => {console.log(key)}, 'postOrderTraverseNode')
複製代碼
  • 複製這段代碼到頁面的script標籤中 斷點調試

代碼分析

  1. Node 初始化的節點對象 它包含 left right 屬性
  2. insert 判斷是否有根節點,沒有的話初始化當前的key爲根節點
  3. insterNode 執行二叉法
    • 判斷新節點的 leftright是否爲空 爲空的話讓其賦值
    • 小於的放 left 大於的 放 right
    • 若是出現既小於 || 大於 又不爲空的狀況 那就遞歸執行 insterNode(newNode.left || right , newNode) 置到 能給子節點賦值爲止

中序排序

  • 代碼實現
//中序排序
                const inOrderTraverseNode = (node, callback) => {
                    if (node !== null) {
                        inOrderTraverseNode(node.left, callback)
                        callback(node.key)
                        inOrderTraverseNode(node.right, callback)
                    }
                }
複製代碼
  • 圖片演示

二叉樹—中序排序

前序排序

  • 代碼實現
//前序遍歷
                const preOrderTraverseNode = (node, callback) => {
                    if (node !== null) {
                        callback(node.key)
                        preOrderTraverseNode(node.left, callback)
                        preOrderTraverseNode(node.right, callback)
                    }
                }
複製代碼
  • 圖片演示
    二叉樹—前序排序

後序排序

  • 代碼實現
//後序遍歷
                const postOrderTraverseNode = (node, callback) => {
                    if (node !== null) {
                        postOrderTraverseNode(node.left, callback)
                        postOrderTraverseNode(node.right, callback)
                        callback(node.key)
                    }
                }
複製代碼
  • 圖片演示
    二叉樹—後序排序

總結

  • 二叉樹的算法在海量數據的排序上相比於其餘排序算法效率要高不少,
  1. 中序遍歷至關於數組的升序排列,
  2. 前序遍歷是對相同二叉樹的賦值,可是對於從新排列一個相同結構二叉樹來講,效率也要高不少,
  3. 後序遍歷至關於對數組的降序排列
相關文章
相關標籤/搜索