js實現二叉樹

二叉樹

  • 二叉樹排序是一種數據結構、根據左孩子小於根節點、右孩子大於根節點的順序進行構造
  • 任意給一個數組,對其進行二叉樹排序。
function BinaryTree() {
    
    // 二叉樹的節點  
    let Node = function (key) {
        this.key = key; //當前節點的值
        this.left = null; // 左孩子
        this.right = null; // 右孩子
    }

    // 插入子節點
    let insertNode = function (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);
            }
        }
    }

    // 初始化根節點、就是一個數組的第一個元素當作二叉樹的根節點
    let root = null; 

    this.insert = function (key) {
        let newNode = new Node(key);
        if(root === null){
            root = newNode;
        }else{
            insertNode(root,newNode)
        }
    };

    // 查看二叉樹結構
    this.show = function () {
        console.log(root);
    }

    // 中序遍歷
    let inOrderTraverseNode = function (node,callback) {
        if(node !== null){
            inOrderTraverseNode(node.left,callback);
            callback(node.key);
            inOrderTraverseNode(node.right,callback)
        }
    }

    this.inOrderTraverse = function (callback) {
        inOrderTraverseNode(root,callback)
    }

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

    this.preOrderTraverse = function (callback) {
        preOrderTraverseNode(root,callback)
    }

    // 後序遍歷
    let nextOrderTraverseNode = function (node,callback) {
        if(node !== null){
            nextOrderTraverseNode(node.left,callback);
            nextOrderTraverseNode(node.right,callback);
            callback(node.key);
        }
    }

    this.nextOrderTraverse = function (callback) {
        nextOrderTraverseNode(root,callback);
    }

}
  • 調用
let nodes  =  [18,13,102,11,6,14,4,7,131];
const bt = new BinaryTree();

nodes.forEach( key => {
    bt.insert(key)
})

bt.show()

// 中序遍歷
// bt.inOrderTraverse((key) => {
//  console.log(key);
// })

// 前序遍歷
// bt.preOrderTraverse((key) => {
//  console.log(key);
// })

// 後序遍歷
bt.nextOrderTraverse((key) => {
    console.log(key);
})
  • 二叉樹遍歷
  1. 中序遍歷
    1. 首先遍歷左子樹、而後遍歷根節點、最後遍歷右子樹 -- 左-根-右
    2. 做用: 將一個二叉樹進行升序排序輸出
  2. 前序遍歷
    1. 首先遍歷根節點、而後遍歷左子樹、最後遍歷右子樹 -- 根-左-右
    2. 做用: 複製一個二叉樹、複製一個二叉樹比從新生成一個二叉樹的效率高10倍左右
  3. 後序遍歷
    1. 首先遍歷左子樹、而後遍歷右子樹、最後遍歷根節點 -- 左-右-根
    2. 適用於操做系統的文件遍歷
  • 二叉樹查找
  1. 查找最小值
  2. 查找最大值
  3. 查找某一個值
// 查找最小值
let minNode = function (node) {
    if(node){
        while(node && node.left !== null){
            node = node.left;
        }

        return node.key;
    }

    return null;
}

this.min = function () {
    return minNode(root);
}

// 查找最大值
let maxNode = function (node) {
    if(node){

        while(node && node.right !== null){
            node = node.right;
        }

        return node.key;
    }

    return null;
}

this.max = function () {
    return maxNode(root);
}

// 查找某個具體的值
let findNode = function (node,key) {
    if(node === null){
        return false;
    }

    // 如果查找的值小於當前節點的值,那麼就去其左子樹進行查找
    // 如果大於,就去右子樹進行查找
    // 如果相等 則返回true 表明存在
    if(key < node.key){
        return findNode(node.left,key)
    }else if(key > node.key){
        return findNode(node.right, key)
    }else{
        return true;
    }
}

this.find = function (key) {
    return findNode(root,key);
}
  • 調用
// 最小值
// console.log(bt.min());

// 最大值
// console.log(bt.max());

// 查找某一個值是否存在二叉樹中
console.log(bt.find(12)); // false
console.log(bt.find(14)); // true
  • 刪除子節點
// 刪除子節點
let removeNode = function (node,key) {
    if(node === null) {
        return null;
    }

    if(key < node.key){
        node.left = removeNode(node.left, key)
        return node;
    }else if(key > node.key){
        node.right = removeNode(node.right, key)
        return node
    }else{
        // 是葉子節點
        if(node.left === null && node.right === null){
            node = null;
            return node;
        }

        if(node.left === null){
            //  只有右子樹
            node = node.right;
            return node;
        }else if(node.right === null){
            // 只有左子樹
            node = node.left;
            return node;
        }

        // 含有左右子節點
        let aux = findMinNode(node.right);
        node.key = aux.key;
        node.right = removeNode(node.right,aux.key);
        return node;
    }
}

this.remove = function (key) {
    root = removeNode(root,key);
}
  • 調用
// 刪除葉子節點
bt.inOrderTraverse((key) => {
    console.log(key);
})
console.log('-----');
bt.remove(4)
bt.inOrderTraverse((key) => {
    console.log(key);
})
  • 所有代碼
function BinaryTree() {
    
    // 二叉樹的節點  
    let Node = function (key) {
        this.key = key; //當前節點的值
        this.left = null; // 左孩子
        this.right = null; // 右孩子
    }

    // 插入子節點
    let insertNode = function (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);
            }
        }
    }

    // 初始化根節點、就是一個數組的第一個元素當作二叉樹的根節點
    let root = null; 

    this.insert = function (key) {
        let newNode = new Node(key);
        if(root === null){
            root = newNode;
        }else{
            insertNode(root,newNode)
        }
    };

    // 查看二叉樹結構
    this.show = function () {
        console.log(root);
    }

    // 中序遍歷
    let inOrderTraverseNode = function (node,callback) {
        if(node !== null){
            inOrderTraverseNode(node.left,callback);
            callback(node.key);
            inOrderTraverseNode(node.right,callback)
        }
    }

    this.inOrderTraverse = function (callback) {
        inOrderTraverseNode(root,callback)
    }

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

    this.preOrderTraverse = function (callback) {
        preOrderTraverseNode(root,callback)
    }

    // 後序遍歷
    let nextOrderTraverseNode = function (node,callback) {
        if(node !== null){
            nextOrderTraverseNode(node.left,callback);
            nextOrderTraverseNode(node.right,callback);
            callback(node.key);
        }
    }

    this.nextOrderTraverse = function (callback) {
        nextOrderTraverseNode(root,callback);
    }

    // 查找最小值
    let minNode = function (node) {
        if(node){
            while(node && node.left !== null){
                node = node.left;
            }

            return node.key;
        }

        return null;
    }

    this.min = function () {
        return minNode(root);
    }

    // 查找最大值
    let maxNode = function (node) {
        if(node){

            while(node && node.right !== null){
                node = node.right;
            }

            return node.key;
        }

        return null;
    }

    this.max = function () {
        return maxNode(root);
    }

    // 查找某個具體的值
    let findNode = function (node,key) {
        if(node === null){
            return false;
        }

        // 如果查找的值小於當前節點的值,那麼就去其左子樹進行查找
        // 如果大於,就去右子樹進行查找
        // 如果相等 則返回true 表明存在
        if(key < node.key){
            return findNode(node.left,key)
        }else if(key > node.key){
            return findNode(node.right, key)
        }else{
            return true;
        }
    }

    this.find = function (key) {
        return findNode(root,key);
    }

    // 查找最小子節點
    let findMinNode = function (node) {
        if(node){
            while(node && node.left !== null){
                return node
            }
        }

        return null;
    }

    // 刪除葉子節點
    let removeNode = function (node,key) {
        if(node === null) {
            return null;
        }

        if(key < node.key){
            node.left = removeNode(node.left, key)
            return node;
        }else if(key > node.key){
            node.right = removeNode(node.right, key)
            return node
        }else{
            // 是葉子節點
            if(node.left === null && node.right === null){
                node = null;
                return node;
            }

            if(node.left === null){
                //  只有右子樹
                node = node.right;
                return node;
            }else if(node.right === null){
                // 只有左子樹
                node = node.left;
                return node;
            }

            // 含有左右子節點
            let aux = findMinNode(node.right);
            node.key = aux.key;
            node.right = removeNode(node.right,aux.key);
            return node;
        }
    }

    this.remove = function (key) {
        root = removeNode(root,key);
    }

}

let nodes  =  [18,13,102,11,6,14,4,7,131];
const bt = new BinaryTree();

nodes.forEach( key => {
    bt.insert(key)
})

// bt.show()

// 中序遍歷
// bt.inOrderTraverse((key) => {
//  console.log(key);
// })

// 前序遍歷
// bt.preOrderTraverse((key) => {
//  console.log(key);
// })

// 後序遍歷
// bt.nextOrderTraverse((key) => {
//  console.log(key);
// })

// 最小值
// console.log(bt.min());

// 最大值
// console.log(bt.max());

// 查找某一個值是否存在二叉樹中
// console.log(bt.find(12)); // false
// console.log(bt.find(14)); // true

// 刪除葉子節點
bt.inOrderTraverse((key) => {
    console.log(key);
})
console.log('-----');
bt.remove(4)
bt.inOrderTraverse((key) => {
    console.log(key);
})
相關文章
相關標籤/搜索