zoukankan      html  css  js  c++  java
  • javaScript实现平衡树

    const Compare ={
        LESS_THAN:-1,
        BIGGER_THAN:1,
        EQUALS:0
    }
    class Node{
        constructor(key){
            this.key = key;
            this.left = null;
            this.right = null;
        }
    }
    function defaultCompare(a,b){
        return a == b ? Compare.EQUALS:(a < b) ? Compare.LESS_THAN : Compare.BIGGER_THAN;
    }
    class BinarySearchTree{
        constructor(comPareFn = defaultCompare){
            this.root = null;
            this.comPareFn = comPareFn;
        }
    
        insert(key){
            if(this.root == null){
                this.root = new Node(key);
            }else{
                this.insertNode(this.root,key);
            }
            
        }
        insertNode(node,key){
            if(this.comPareFn(key,node.key) === Compare.LESS_THAN){
                if(node.left == null){
                    node.left = new Node(key);      
                }else{
                    this.insertNode(node.left,key);
                }
            }else{
                if(node.right == null){
                    node.right = new Node(key);
                }else{
                    this.insertNode(node.right,key);
                }
            }
        }
        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;
            }
        }
        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(node){
            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);
        }
        preTraverse(callback){
            this.preTraverseNode(this.root,callback);
        }
        preTraverseNode(node,callback){
            if(node == null){
                return;
            }
            callback(node.key);
            this.preTraverseNode(node.left,callback);
            this.preTraverseNode(node.right,callback);
        }
        postTraverse(callback){
            this.postTraverseNode(this.root,callback);
        }
        postTraverseNode(node,callback){
            if(node == null){
                return;
            }
            this.postTraverseNode(node.left,callback);
            this.postTraverseNode(node.right,callback);
            callback(node.key);
        }
        remove(key){
            this.root =  this.removeNode(this.root,key);
        }
        removeNode(node,key){
            if(node == null){
                return false;
            }
            if(this.comPareFn(key,node.key) === Compare.LESS_THAN){
                node.left =  this.removeNode(node.left,key);
                return node;
            }else if(this.comPareFn(key,node.key) === Compare.BIGGER_THAN){
                node.right =  this.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;
                }
                if(node.right == null){
                    node = node.left;
                    return node;
                }
                let tmp = this.minNode(node.right);
                node.key = tmp.key;
                node.right = this.removeNode(node.right,tmp.key);
                return node;
            }
        }
    }
    
    const BalanceFactor ={
        UNBALANCED_RIGHT:1,
        SLIGHTLY_UNBALANCED_RIGHT:2,
        BALANCED:3,
        UNBALANCED_LEFT:4,
        SLIGHTLY_UNBALANCED_LEFT:5
    }
    
    const printNode = (value) => console.log(value);
    class AVLTree extends BinarySearchTree{
        constructor(comPareFn = defaultCompare){
            super(comPareFn);
        }
        getNodeHeight(node){
            if(node == null){
                return -1;
            }
            return Math.max(
                this.getNodeHeight(node.left),this.getNodeHeight(node.right)
                )+1;
         }
         getBalanceFactor(node){
            const factor = this.getNodeHeight(node.left) - this.getNodeHeight(node.right);
            switch(factor){
                case 1:
                   return BalanceFactor.SLIGHTLY_UNBALANCED_LEFT;
                case 2:
                   return BalanceFactor.UNBALANCED_LEFT;
                case -1:
                   return BalanceFactor.SLIGHTLY_UNBALANCED_RIGHT;
                case -2:
                   return BalanceFactor.UNBALANCED_RIGHT;
                default:
                   return BalanceFactor.BALANCED;
            }
        }
        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 balanceFactor = this.getBalanceFactor(node);
            if(balanceFactor === BalanceFactor.UNBALANCED_LEFT){
                if(this.comPareFn(key,node.key) === Compare.LESS_THAN){
                    node =  this.rotationLL(node);
                }else{
                    return this.rotationLR(node);
                }
            }else if(balanceFactor === BalanceFactor.UNBALANCED_RIGHT){
                if(this.comPareFn(key,node.key) === Compare.BIGGER_THAN){
                    node =  this.rotationRR(node);
                }else{
                    return this.rotationRL(node);
                }
            }
            return node;
        }
        rotationLL(node){
            const tmp = node.left;
            node.left = tmp.right;
            tmp.right = node;
            node = tmp;
            return tmp;
        }
        rotationRR(node){
            const 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);
        }
        remove(key){
            this.root = this.removeNode(this.root,key);
        }
        removeNode(node,key){
            node = super.removeNode(node,key);
            if(node == null){
                return node;
            }
            let balanceFactor = this.getBalanceFactor(node);
            if(balanceFactor === BalanceFactor.UNBALANCED_LEFT){
                let balanceFactor = this.getBalanceFactor(node.left);
                if(balanceFactor == BalanceFactor.SLIGHTLY_UNBALANCED_LEFT || balanceFactor == BalanceFactor.BALANCED){
                    return this.rotationLL(node);
                }
                if(balanceFactor == BalanceFactor.SLIGHTLY_UNBALANCED_RIGHT){
                    return this.rotationLR(node.left);
                }
            }
            if(balanceFactor === BalanceFactor.UNBALANCED_RIGHT){
                let balanceFactor = this.getBalanceFactor(node.left);
                if(balanceFactor == BalanceFactor.SLIGHTLY_UNBALANCED_RIGHT || balanceFactor == BalanceFactor.BALANCED){
                    return this.rotationRR(node);
                }else if(balanceFactor == BalanceFactor.SLIGHTLY_UNBALANCED_LEFT){
                    return this.rotationRL(node.right);
                }
            }
            return node;
        }
    }
  • 相关阅读:
    v-bind绑定属性样式——class的三种绑定方式
    vue知识点15
    iOS开发——heightForHeaderInSection设置高度无效
    iOS开发——AFNetworking基于https的使用
    iOS开发——循环遍历的比较
    iOS开发——Block使用小结
    iOS开发——GCD总结
    iOS开发者中心重置设备列表
    iOS开发—— Couldn't add the Keychain Item
    iOS——扬声器与听筒的切换
  • 原文地址:https://www.cnblogs.com/MySweetheart/p/13288168.html
Copyright © 2011-2022 走看看