JavaScript数据结构之 二叉排序树

/**
 * 二叉排序树(Binary Sort Tree)又称二叉查找树(Binary Search Tree),亦称二叉搜索树。
 * 左边子节点的值 < 父节点的值 < 右边子节点的值
 * 包括的方法有:插入、遍历、查询、查询父节点、右树上最小节点、
 * 前中后序遍历、清空、删除、是否为空、求宽度、求深度
 */

function BinarySortTree(value){
    this.root = null;
    if(typeof value === "number"){
        this.root = this.insert(value);
    }else{
        return false;
    }
}
BinarySortTree.prototype = {
    //创建节点
    createNode: function(value){
        return {
            value:value,
            left:null,
            right:null
        };
    },
    //插入一个新节点,如果没有root就创建root
    insert: function(value){
        if(typeof value !== "number"){
            return false;
        }
        var node = this.createNode(value);
        if(!this.root){
            this.root = node;
            return this.root;
        }else{
            return this.insertNode(this.root, node);
        }
    },
    //通过递归来插入
    insertNode: function(fNode, newNode){
        if(fNode.value>newNode.value){
            if(fNode.left===null){
                fNode.left = newNode;
                return newNode;
            }else{
                return this.insertNode(fNode.left, newNode);
            }
        }else if(fNode.value<newNode.value){
            if(fNode.right===null){
                fNode.right = newNode;
                return newNode;
            }else{
                return this.insertNode(fNode.right, newNode);
            }
        }else{
            return false;
        }
    },
    //查找第一个值相同的节点
    findFirst: function(value){
        console.log(this.root);
        if(!this.root)return false;
        return this.findFirstNode(this.root, value)
    },
    //采用的是前序查找 中>左>右
    findFirstNode: function(node, value){
        if(node === null)return false;
        if(node.value === value)return node;
        else if(node.value > value){
            return this.findFirstNode(node.left, value);
        }
        else{
            return this.findFirstNode(node.right, value);
        }
    },
    //判断空树
    isEmpty: function(){
        if(this.root)return false;
        return true;
    },
    //清空二叉树
    clear: function(){
        this.clearTree(this.root);
        this.root = null;
    },
    //清理某个子树, 需要找到父节点,然后设为null,不能直接将node设为null
    clearTree: function(node){
        if(node === null)return;
        this.clearTree(node.left);
        this.clearTree(node.right);
        var fNode = this.findFather(node);
        if(fNode.left === node)fNode.left=null;
        else if(fNode.right === node)fNode.right=null;
    },
    //寻找父节点
    findFather: function(node){
        return this.findFatherNode(this.root,node);
    },
    findFatherNode: function(fNode, node){
        if(fNode===null)return false;
        if(fNode.left === node || fNode.right === node)return fNode;
        if(fNode.value>node.value)return this.findFatherNode(fNode.left, node);
        else return this.findFatherNode(fNode.right, node);
    },
    //计算二叉树深度
    getDepth: function(){
        return this.getTreeDepth(this.root);
    },
    //计算子树深度
    getTreeDepth: function(node){
        if(node === null)return 0;
        var leftDepth = this.getTreeDepth(node.left) + 1;
        var rightDepth = this.getTreeDepth(node.right) + 1;

        if(leftDepth>rightDepth)
            return leftDepth;
        return rightDepth;
    },
    //计算树的宽度
    getWidth: function(){
        return this.getLeftTreeWidth(this.root)+this.getRightTreeWidth(this.root)-1;
    },
    //计算子树宽度
    getLeftTreeWidth: function(node){
        if(node === null)return 0;
        return 1+this.getLeftTreeWidth(node.left);
    },
    getRightTreeWidth: function(node){
        if(node === null)return 0;
        return 1+this.getRightTreeWidth(node.right);
    },
    //前序遍历
    preOrderTraverse: function(callback){
        this.preOrderTraverseNode(this.root, callback);
    },
    preOrderTraverseNode: function(node, callback){
        if(node === null)return;
        //left
        this.preOrderTraverseNode(node.left, callback);
        //callback
        callback(node.value);
        //right
        this.preOrderTraverseNode(node.right, callback);
    },

    //中序遍历
    inOrderTraverse: function(callback){
        this.inOrderTraverseNode(this.root, callback);
    },
    inOrderTraverseNode: function(node, callback){
        if(node === null)return;
        //callback
        callback(node.value);
        //left
        this.inOrderTraverseNode(node.left, callback);
        //right
        this.inOrderTraverseNode(node.right, callback);
    },

    //后序遍历
    postOrderTraverse: function(callback){
        this.postOrderTraverseNode(this.root, callback);
    },
    postOrderTraverseNode: function(node, callback){
        if(node === null)return;
        //left
        this.postOrderTraverseNode(node.left, callback);
        //right
        this.postOrderTraverseNode(node.right, callback);
        //callback
        callback(node.value);
    },
    //找到右树的最小值
    findRightMinNode: function(node){
        if(node.left===null)return node;
        else return this.findRightMinNode(node.left);
    },

    //移除
    remove: function(value){
        return this.removeNode(this.root, value);
    },
    removeNode: function(node, value){
        var targetNode = this.findFirstNode(node, value);
        var fNode = this.findFather(targetNode);
        if(targetNode===this.root){
            return false;//暂不考虑移除根节点情况
        }
        //target为叶子节点
        if(targetNode.left===null&&targetNode.right===null){
            fNode.left === targetNode?fNode.left=null:fNode.right=null;
            return true;
        }
        //target只有一个子节点
        if(targetNode.left===null&&targetNode.right){
            fNode.left === targetNode?fNode.left=targetNode.right:fNode.right=targetNode.right;
            delete targetNode.value;
            delete targetNode.right;
            delete targetNode.left;
            return true;
        }
        if(targetNode.right===null&&targetNode.left){
            fNode.left === targetNode?fNode.left=targetNode.left:fNode.right=targetNode.left;
            delete targetNode.value;
            delete targetNode.right;
            delete targetNode.left;
            return true;
        }
        //target有两个子节点
        var minNode = this.findRightMinNode(targetNode.right);
        targetNode.value = minNode.value;
        return this.removeNode(targetNode.right, targetNode.value);
    }
};


var root = new BinarySortTree(0);
root.insert(1);
root.insert(2);
root.insert(8);
root.insert(4);
root.insert(9);
root.insert(-7);
root.insert(-1);
root.insert(-8);

console.log(root);

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章