• js的红黑树


    const Compare ={
        LESS_THAN:-1,
        BIGGER_THAN:1,
        EQUALS:0
    }
    const BalancedFactor = {
        UNBALANCED_LEFT:1,
        SLIGHTLY_UNBALANCED_LEFT:2,
        BALANCED:3,
        UNBALANCED_RIGHT:4,
        SLIGHTLY_UNBALANCED_RIGHT:5
    }
    function defaultCompare(a,b){
        return a === b ? Compare.EQUALS:(a<b)?Compare.LESS_THAN:Compare.BIGGER_THAN;
    }
    class Node{
        constructor(key){
            this.key = key;
            this.left = null;
            this.right = null;
        }
    }
    class BinarySearchTree{
        constructor(compareFn = defaultCompare){
            this.root = null;
            this.compareFn = compareFn;
        }
        insert(key){
            this.root = this.insertNode(this.root,key);
        }
        insertNode(node,key){
            if(node == null){
                return new Node(key);
            }
            if(this.compareFn(key,node.key) === Compare.LESS_THAN){
                node.left = this.insertNode(node.left,key);
            }
            else if(this.compareFn(key,node.key) === Compare.BIGGER_THAN){
                node.right = this.insertNode(node.right,key);
            }else{
                return node;
            }
            return node;
        }
        search(key){
            return this.searchNode(this.root,key);
        } 
        searchNode(node,key){
            if(node == null){
                return false;
            }
            if(this.compareFn(key,node.key) === Compare.LESS_THAN){
                return this.searchNode(node.left,key);
            }
            else if(this.compareFn(key,node.key) === Compare.BIGGER_THAN){
                return this.searchNode(node.right,key);
            }else{
                return true;
            }
        }
        remove(key){
            this.root = this.removeNode(this.root,key);
        }
        removeNode(node,key){
            if(node == null){
                return node;
            }
            if(this.compareFn(key,node.key) === Compare.LESS_THAN){
                node.left = this.removeNode(node.left,key);
            }else if(this.compareFn(key,node.key) === Compare.BIGGER_THAN){
                node.right = this.removeNode(node.right,key);
            }else{
                if(node.left == null && node.right == null){
                    node = null;
                    return node;
                }
                if(node.left == null){
                    node = node.right;
                    return node;
                }
                if(node.right == null){
                    node = node.left;
                    return node;
                }
               let aux = this.minNode(node.right);
               node.key = aux.key;
               node = this.removeNode(node.right,aux.key);
               return node;
            }
            return node;
        }
        min(){
            return this.minNode(this.root);;
        }
        minNode(node){
            if(node == null){
                return node;
            }
            while(node.left!=null){
                node = node.left;
            }
            return node;
        }
        max(){
            return this.maxNode(this.root);
        }
        maxNode(){
            if(node == null){
                return node;
            }
            while(node.right != null){
                node = node.right;
            }
            return node;
        }
        inOrderTraverse(callback){
            this.inOrderTraverseNode(this.root,callback);
        }
        inOrderTraverseNode(node,callback){
            if(node == null)return;
            this.inOrderTraverseNode(node.left,callback);
            callback(node.key);
            this.inOrderTraverseNode(node.right,callback);    
        }
        inPostTraverse(callback){
            this.inPostTraverseNode(this.root,callback);
        }
        inPostTraverseNode(node,callback){
            if(node == null)return; 
            this.inPostTraverseNode(node.left,callback);
            this.inPostTraverseNode(node.right,callback);
            callback(node.key);   
        }
        inPreTraverse(callback){
            this.inPreTraverseNode(this.root,callback);
        }
        inPreTraverseNode(node,callback){
            if(node == null){
                return; 
            } 
            callback(node.key);
            this.inPreTraverseNode(node.left,callback);
            this.inPreTraverseNode(node.right,callback);  
        }
    }
    class AVLTree extends BinarySearchTree{
        constructor(compareFn = defaultCompare){
            super(compareFn);
        }
        insert(key){
            this.root = this.insertNode(this.root,key);
        }
        insertNode(node,key){
            if(node == null){
                return new Node(key);
            }
            if(this.compareFn(key,node.key) === Compare.LESS_THAN){
                node.left = this.insertNode(node.left,key);
            }else if(this.compareFn(key,node.key) === Compare.BIGGER_THAN){
                node.right = this.insertNode(node.right,key);
            }else{
                return node;
            }
            const balancedFactor = this.getBalanceFactor(node);
            if(balancedFactor === BalancedFactor.UNBALANCED_LEFT){
                if(this.compareFn(key,node.key) === Compare.LESS_THAN){
                    node = this.rotationLL(node);
                }else{
                    node = this.rotationLR(node.left);
                }
            }
            if(balancedFactor === BalancedFactor.UNBALANCED_RIGHT){
                if(this.compareFn(key,node.key) === Compare.BIGGER_THAN){
                    node = this.rotationRR(node);
                }else{
                    node = this.rotationRL(node.right);
                }
            }
            return node;
        }
        remove(key){
            this.root = this.removeNode(this.root,key);
        }
        removeNode(node,key){
            node = super.removeNode(node,key);
            if(node == null){
                return node;
            }
            if(this.compareFn(key,node.key) === Compare.LESS_THAN){
                node.left = this.removeNode(node.left,key);
            }else if(this.compareFn(key,node.key) === Compare.BIGGER_THAN){
                node.right = this.removeNode(node.right,key);
            }else{
                return node;
            }
            const balancedFactor = this.getBalanceFactor(node);
            if(balancedFactor == BalancedFactor.UNBALANCED_LEFT){
                const leftBalancedFactor = this.getBalanceFactor(node.left);
                if(leftBalancedFactor == BalancedFactor.BALANCED|| leftBalancedFactor == BalancedFactor.SLIGHTLY_UNBALANCED_LEFT){
                    node = this.rotationLL(node);
                }
                if(leftBalancedFactor == BalancedFactor.SLIGHTLY_UNBALANCED_RIGHT){
                    node = this.rotationLR(node.left);
                }
            }
            if(balancedFactor == BalancedFactor.UNBALANCED_RIGHT){
                const rightBalancedFactor = this.getBalanceFactor(node.right);
                if(rightBalancedFactor == BalancedFactor.BALANCED || rightBalancedFactor == BalancedFactor.SLIGHTLY_UNBALANCED_RIGHT){
                    node = this.rotationRR(node);
                }
                if(rightBalancedFactor == BalancedFactor.SLIGHTLY_UNBALANCED_RIGHT){
                    node = this.rotationRL(node.right);
                }
            }
            return node;
        }
        rotationLL(node){
            let tmp = node.left;
            node.left =tmp.right;
            tmp.right = node;
            return tmp;
        }
        rotationRR(node){
            let tmp = node.right;
            node.right = tmp.left;
            tmp.left = node;
            return tmp;
        }
        rotationLR(node){
            node.left = this.rotationLL(node.left);
            return this.rotationRR(node);
        }
        rotationRL(node){
            node.right = this.rotationRR(node.right);
            return this.rotationLL(node);
        }
        getBalanceFactor(node){
            if(node == null){
                return;
            }
            let balanceFactor = this.getDifferenceHeight(node.left) - this.getDifferenceHeight(node.right);
            switch(balanceFactor){
                case 1:
                    return BalancedFactor.SLIGHTLY_UNBALANCED_LEFT;
                case 2:
                    return BalancedFactor.UNBALANCED_LEFT;
                case -1:
                    return BalancedFactor.SLIGHTLY_UNBALANCED_RIGHT;
                case -2:
                    return BalancedFactor.UNBALANCED_RIGHT;
                default:
                    return BalancedFactor.BALANCED;
            }
        }
        getDifferenceHeight(node){
           if(node == null){
               return -1;
           }
           return Math.max(this.getDifferenceHeight(node.left),this.getDifferenceHeight(node.right))+1;
        }
    }
    printNode = (value)=>console.log(value);
    class RedBlackNode extends Node{
        constructor(key){
            super(key);
            this.key = key;
            this.color = Colors.RED;
            this.parent = null;
        }
        isRed(){
            return this.color === Colors.RED;
        }
    }
    const Colors ={
        RED:0,
        BLACK:1
    }
    class RedBlackTree extends BinarySearchTree{
        constructor(compareFn = defaultCompare){
            super(compareFn);
            this.compareFn = compareFn;
            this.root = null;
        }
        insert(key){
            if(this.root == null){
                this.root = new RedBlackNode(key);
                this.root.color = Colors.BLACK;
            }else{
                const newNode = this.insertNode(this.root,key);
                this.fixTreeProperties(newNode);
            }
        }
        insertNode(node,key){
            if(this.compareFn(key,node.key) === Compare.LESS_THAN){
                if(node.left == null){
                    node.left = new RedBlackNode(key);
                    node.left.parent = node;
                    return node.left;//返回当前的节点
                }else{
                    return this.insertNode(node.left,key);
                }
            }
            else{
                if(node.right == null){
                    node.right = new RedBlackNode(key);
                    node.right.parent = node;
                    return node.right;
                }else{
                    return this.insertNode(node.right,key);
                }
            }
        }
        fixTreeProperties(node){
            //判断新节点,和新节点的父节点存不存在,以及父节点是否为红色,新节点是否为红色
            while(node&&node.parent&&node.parent.color == Colors.RED && node.color != Colors.BLACK ){
                let parent = node.parent;//获取父节点
                const grandParent = parent.parent;//获取祖节点
                //如果父节点是祖节点的左子节点
                if(grandParent && grandParent.left == parent){
                    //获取叔节点
                    const uncle = grandParent.right;
                    //如果叔节点存在,并且叔节点的颜色是红色
                    if(uncle && uncle.color == Colors.RED){
                        grandParent.color = Colors.RED;
                        parent.color = Colors.BLACK;
                        uncle.color = Colors.BLACK;
                        node = grandParent;
                    }else{//如果叔节点的颜色为黑色
                        //新节点位于父节点的右边
                        if(node == parent.right){
                            this.rotationRR(parent);
                            node = parent;
                            parent = node.parent;
                        }
                        //新节点位于父节点的左边
                        this.rotationLL(grandParent);
                        parent.color = Colors.BLACK;//parent现在是祖节点
                        grandParent.color = Colors.RED;
                        node = parent;
                    }
                }else{
                    const uncle = grandParent.left;
                    if(uncle && uncle.color !== Colors.BLACK){
                        grandParent.color = Colors.RED;
                        parent.color = Colors.BLACK;
                        uncle.color = Colors.BLACK;
                        node = grandParent;
                    }else{
                        if(node == parent.left){
                            this.rotationLL(parent);
                            node = parent;
                            parent = node.parent;
                        }
                        this.rotationRR(grandParent);
                        parent.color = Colors.BLACK;
                        grandParent.color = Colors.RED;
                        node = parent;
                    }
                }
            }
            this.root.color = Colors.BLACK;
        }
        rotationLL(node){
            //获取父节点的左子节点
            const tmp = node.left;
            //父节点的左子节点指向tmp的右子节点
            node.left = tmp.right;
            //如果tmp的左子节点存在
            if(tmp.right && tmp.right.key){
                //tmp的右子节点的父亲指向父节点
               tmp.right.parent = node;
            }
            //tmp指向父节点的父亲;
            tmp.parent = node.parent;
            if(!node.parent){
                this.root = tmp;
            }else{
                  //判断父节点是祖节点的左节点还是右节点
                if(node == node.parent.left){
                    //祖节点的左子节点是tmp
                    node.parent.left = tmp;
                }else{
                    node.parent.right = tmp;
                }
            }
            //父节点成为tmp的右子节点
            tmp.right = node;
            //父节点的父亲是tmp
            node.parent = tmp;
        }
        rotationRR(node){
            const tmp = node.right;
            node.right = tmp.left;
            if(tmp.left && tmp.left.key){
                tmp.left.parent = node;
            }
            tmp.parent = node.parent;
            if(!node.parent){
                this.root = tmp;
            }else{
                if(node ==  node.parent.left){
                    node.parent.left = tmp;
                }else{
                    node.parent.right = tmp;
                }
            }
            tmp.left = node;
            node.parent = tmp;
        }
    }

  • 相关阅读:
    Linux下链接数据库图形化工具
    基于深度学习的中文语音识别系统框架(pluse)
    Centos配置深度学习开发环境
    aishell数据处理为thchs30格式
    GRU-CTC中文语音识别
    深度学习知识树,别处传过来,用于自己知识整理。
    kaldi HMM-GMM全部训练脚本分解
    使用深度学习来破解 captcha 验证码(转)
    kaldi
    神经网络最优化方法
  • 原文地址:https://www.cnblogs.com/MySweetheart/p/13306028.html
Copyright © 2020-2023  润新知