八、树

 

位于树顶部的节点叫做根节点,它没有父节点。树中的每个元素都叫作节点,节点分为内部节点和外部节点。至少有一个子节点的节点称为内部节点。没有子元素的节点称为外部节点或叶节点。

子树:由节点(非根节点)和它的后代构成。

节点的深度:取决于它的祖先节点的数量。

树的高度:取决于所有节点深度的最大值。一棵树也可以被分解成层级。根节点在第0层,它的子节点在第1层,依次类推。

遍历:访问树的每一个节点并对它们进行某种操作的过程。

 

二叉树与二叉搜索树

二叉树中的节点最多只能有两个子节点:一个是左侧子节点,另一个是右侧子节点。

二叉搜索树(BST)是二叉树的一种,但是它只允许在左侧存储(比父节点)小的值,在右侧节点存储(比父节点)大或等于的值。

相关代码

function BinarySearchTree() {
    var Node = function (key) {
        this.left = null;
        this.key = key;
        this.right = null;
    }
    var root = null;
    // 添加节点
    var 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)
            }
        }


    }
    this.add = function (key) {
        var newNode = new Node(key)
        if (root === null) {
            root = newNode;
        } else {
            insertNode(root, newNode)
        }
    }
    // 中序遍历:顺序为左侧子节点、父节点、右侧子节点
    var 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)
    }

    // 先序遍历:顺序为父节点、左侧子节点、右侧子节点
    var 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)
    }

    // 后序遍历:顺序为左侧子节点、右侧子节点、父节点
    var postOrderTraverseNode = function (node, callback) {
        if (node !== null) {
            postOrderTraverseNode(node.left, callback)
            postOrderTraverseNode(node.right, callback)
            callback(node.key)
        }
    }
    this.postOrderTraverse = function (callback) {
        postOrderTraverseNode(root, callback)
    }

    // 最小值
    var minNode = function (node) {
        if (node) {
            while (node && node.left !== null) {
                node = node.left;
            }
            return node.key;
        }
        return null;
    }
    this.min = function () {
        return minNode(root);
    }

    // 最大值
    var maxNode = function (node) {
        if (node) {
            while (node && node.right !== null) {
                node = node.right;
            }
            return node.key;
        }
        return null;
    }
    this.max = function () {
        return maxNode(root);
    }

    // 搜索特定值
    this.search = function (key) {
        return searchNode(root, key);
    }
    var searchNode = function (node, key) {
        if (node === null) {
            return false;
        }
        if (key < node.key) {
            return searchNode(node.left, key);
        } else if (key > node.key) {
            return searchNode(node.right, key);
        } else {
            return true;
        }
    }
    // 移除方法
    this.remove = function (key) {
        root = removeNode(root, key);
    }
    var 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 {
            // 键等于node.key
            // 只有一个叶节点
            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;
        }
    }
    var findMinNode = function (node) {
        while (node && node.left !== null){
            node = node.left
        }
        return node;
    }
    // 返回所有节点
    this.val = function () {
        return root;
    }
}

 

posted @ 2019-02-18 16:01  道鼎金刚  阅读(130)  评论(0)    收藏  举报