JavaScript數據結構之-樹

一、它是什麼?

樹一種分層次的數據結構。它是由一個或者多個節點組成由層次關係的集合。之因此稱之爲樹,是由於看它外形像一顆倒掛的樹。根朝上,葉朝下。由若干個節點組成,沒有父節點的節點稱之爲根節點。一個節點只有一個父節點,一個父節點由若干個子節點。node

二、二叉搜索樹(BST)

節點的左子節點小於父節點,節點的右子節點大於父節點。bash

2.一、實現二叉搜索樹的遍歷、新增、查詢、刪除

function BinarySearchTree(){
        // 根節點初始化
        var root = null;
        // 建立節點類
        var Node = function(key) {
            this.key = key;
            this.left = null;
            this.right = null;
        };
        // 建立節點
        this.insert = function(key) {
            var node = new Node(key);
            if (root === null) {
                root = node;
            } else {
                insertNode(root, node);
            }
        };
        // 查找最小值
        this.min = function() {
            var node = root;
            if (node) {
                while (node && node.left !== null) {
                    node = node.left;
                }
                return node.key;
            }
            return null;
        };
        // 查找最大值
        this.max = function() {
            var node = root;
            if (node) {
                while (node && node.right !== null) {
                    node = node.right;
                }
                return node.key;
            }
            return null;
        };
        // 查找特定的值
        this.search = function(key) {
            return searchNode(root, key);
        };
        // 刪除指定節點
        this.remove = function(key) {
            root = removeNode(root, key);
        };
        // 中序遍歷
        this.inOrderTraverse = function(callback) {
            inOrderTraverseNode(root, callback);
        };
        // 先序遍歷
        this.preOrderTraverse = function(callback) {
            preOrderTraverseNode(root, callback);
        };
        // 後續遍歷
        this.postOrderTraverse = function(callback) {
            postOrderTraverseNode(root, callback);
        };
        // 建立節點輔助類
        function insertNode(root, node) {
            if (node.key < root.key) {
                if (root.left === null) {
                    root.left = node;
                } else {
                    insertNode(root.left, node);
                }
            } else {
                if (root.right === null) {
                    root.right = node;
                } else {
                    insertNode(root.right, node);
                }
            }
        }
        // 查找特定值輔助類
        function searchNode(node, key) {
            if (node) {
                if (key < node.key) {
                    return searchNode(node.left, key);
                } else if (key > node.key){
                    return searchNode(node.right, key);
                } else {
                    return true;
                }
            } else {
                return false;
            }
        }
        // 刪除指定值輔助類
        function removeNode(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;
                }
                // 第三種狀況,刪除節點有不少子節點
                // 咱們須要找到刪除節點,右子節點的最小值,用最小節點去更新刪除節點
                var aux = findMinNode(node.right);
                node.key = aux.key;
                node.right = removeNode(node.right, aux.key);
                return node;
            }
        }
        // 查找節點的最小值節點
        function findMinNode(node) {
            while(node && node.left) {
                node = node.left;
            }
            return node;
        }
        // 中序遍歷
        function inOrderTraverseNode(node, callback) {
            if(node) { 
                inOrderTraverseNode(node.left, callback);
                callback(node.key);
                inOrderTraverseNode(node.right, callback);
            }
        }
        // 先序遍歷
        function preOrderTraverseNode(node, callback) {
            if(node) { 
                callback(node.key);
                preOrderTraverseNode(node.left, callback);
                preOrderTraverseNode(node.right, callback);
            }
        }
        // 後序遍歷
        function postOrderTraverseNode(node, callback) {
            if(node) { 
                preOrderTraverseNode(node.left, callback);
                preOrderTraverseNode(node.right, callback);
                callback(node.key);
            }
        }
    }
    var tree = new BinarySearchTree();
    tree.insert(11);
    tree.insert(7);
    tree.insert(15);
    tree.insert(5);
    tree.insert(3);
    tree.insert(9);
    tree.insert(8);
    tree.insert(10);
    tree.insert(10);
    tree.insert(13);
    tree.insert(12);
    tree.insert(14);
    tree.insert(20);
    tree.insert(18);
    tree.insert(25);
    function printNode(value) {
        console.log(value);
    }
    // tree.inOrderTraverse(printNode);
    // tree.preOrderTraverse(printNode);
    // tree.postOrderTraverse(printNode);
    var min = tree.min();
    var max = tree.max();
    var search = tree.search(7);
    tree.remove(10);
    tree.inOrderTraverse(printNode);
複製代碼

三、二叉搜索樹(BST)優勢

二叉樹結合了數據查詢的優化和鏈表插入刪除的優勢。在處理大量動態數據時很是有用。有助於更高效的對數據進行查詢、插入、刪除。數據結構

四、二叉搜索樹(BST)缺點

當添加的節點數,可能會出現一條邊很深的狀況。post

五、解決二叉搜索樹(BST)缺點,自平衡二叉搜索樹(AVL)

自平衡二叉搜索樹在進行節點的添加時,計算AVL樹的每一個節點的左子樹的hl,和右子樹的高度。若是hr-hl的差值不爲一、-一、0三者之一。則須要平衡AVL樹。這就是平衡因子。平衡AVL時,採用AVL旋轉。來處理不平衡的狀態。優化

相關文章
相關標籤/搜索