为了账号安全,请及时绑定邮箱和手机立即绑定

AVL平衡二叉树 AND 旋转 js 版

某度复制过来的:平衡二叉树(Balanced Binary Tree)又被称为AVL树(有别于AVL算法),且具有以下性质:它是一 棵空树或它的左右两个子树的高度差的绝对值不超过1,并且左右两个子树都是一棵平衡二叉树。平衡二叉树的常用实现方法有红黑树、AVL、替罪羊树、Treap、伸展树等。 最小二叉平衡树的节点的公式如下 F(n)=F(n-1)+F(n-2)+1 这个类似于一个递归的数列,可以参考Fibonacci(斐波那契)数列,1是根节点,F(n-1)是左子树的节点数量,F(n-2)是右子树的节点数量。

下面代码是我自己编写 写的代码比较简单应该大多数都看的懂 “吧”

本章主要旋转思想:一共4种情况。第3、4种一定是先旋转成第1、2种。第1、2种情况在旋转成平衡。(左边4种情况、右边4种情况,其实是一样的,我这里就说是4种、一共8种)
(图片网上下载的)
图片描述

<script>
    function Tree(){
        // 根
        var root = null;

        var Node = function (key){
            this.key = key;
            this.left = null;
            this.right = null;
        }
                 // 添加节点
               /*
                *  第3个数指 left || right 用于辨别 左边不平衡还是右边不平衡
                    */
        var insertNode = function (node,newDode,direction){
            if( newDode.key < node.key ){
                if( node.left == null ){
                    // 左边为空添加
                    node.left = newDode;

                    // 判断 是否平衡  取出那个不平衡的节点,下面旋转
                    var balanceNode = new isBalance(root);

                    if( balanceNode.key ){
                        console.log( balanceNode.key , '节点 -- 不平衡' );
                        // 旋转平衡
                        rotate(balanceNode,direction);
                    }

                }else{
                                        // 左边存在的话就递归到为 node.left = null 为止
                    // 递归  left
                    var left = direction || 'left';
                    insertNode(node.left,newDode,left);
                }
            }else{
                if( node.right == null ){
                    // 添加
                    node.right = newDode;

                    // 判断 是否平衡
                    var balanceNode = new isBalance(root);

                    if( balanceNode.key ){
                        console.log( balanceNode.key , '节点 -- 不平衡' );
                        // 旋转平衡
                        rotate(balanceNode,direction);
                    }

                }else{
                    // 递归 right
                    var right = direction || 'right';
                    insertNode(node.right,newDode,right);
                }
            }
        }

        // 旋转 方式   逆时针旋转  顺时
        var rotate = function(balanceNode,direction){
            var nextNode = balanceNode[direction];
            var nextNodeLeft = nextNode.left;
            var nextNodeRight = nextNode.right;

            if( direction == 'right' ){

                // 第三、四种情况,先转成 第一、二种情况

                if( nextNodeLeft && !nextNodeRight ){

                    nextNode.left = null;   
                    balanceNode[direction] = nextNodeLeft;
                    nextNodeLeft.right = nextNode;

                }else if( nextNodeLeft && nextNodeRight && getNodeHeight(nextNodeLeft) > getNodeHeight(nextNodeRight) ){

                    nextNode.left = null;
                    balanceNode[direction] = nextNodeLeft;
                    nextNodeRight.right = nextNode;
                }
                // 将根节点下面一个节点更新位置
                    nextNode = balanceNode[direction];

                if( nextNode.left == null ){
                    nextNode.left = balanceNode;
                    balanceNode.right = null;
                }else{
                    balanceNode.right = nextNode.left;
                    nextNode.left = balanceNode;
                }
            }else if( direction == 'left' ){

                // 第三、四种情况,先转成 第一、二种情况

                if( !nextNodeLeft && nextNodeRight ){

                    nextNode.right = null;  
                    balanceNode[direction] = nextNodeRight;
                    nextNodeRight.left = nextNode;

                }else if( nextNodeLeft && nextNodeRight && getNodeHeight(nextNodeLeft) < getNodeHeight(nextNodeRight) ){

                    nextNode.right = null;
                    balanceNode[direction] = nextNodeRight;
                    nextNodeRight.left = nextNode;

                }
                // 将根节点下面一个节点更新位置
                    nextNode = balanceNode[direction];

                if( nextNode.right == null ){   // 第一种情况
                    nextNode.right = balanceNode;
                    balanceNode.left = null;
                }else{                          // 第二种情况        
                    balanceNode.left = nextNode.right;
                    nextNode.right = balanceNode;
                }   
            }

            // 设置成根节点
                if( root == balanceNode ){
                    root = nextNode;
                }else{
                    var BeforeNode = findBeforeNode(root,balanceNode);

                    BeforeNode[direction] = nextNode;
                }
                // 判断是否还存在不平衡
                var twoBalanceNode = new isBalance(root);

                    if( twoBalanceNode.key ){
                        console.log( twoBalanceNode.key , '节点第2次 -- 不平衡' );
                        rotate(twoBalanceNode,direction);
                    }

        }

        // 当前节点 找到上面一个节点  ->先序算法
        var findBeforeNode = function (Root,node){
            if( Root.left == node || Root.right == node ){
                return Root;
            }else{
                if( Root.left ){
                    var resultL = findBeforeNode(Root.left,node);
                    if( resultL != null ){
                        return resultL;
                    }
                }
                if( Root.right ){
                    var resultR = findBeforeNode(Root.right,node);
                    if( resultR != null ){
                        return resultR;
                    }
                }
                return null;    
            }
        }

        // 判断 是否平衡 返回那个不平衡节点 ( >=2则不平衡)
        var isBalance = function(node){
            var leftTree = getNodeHeight(node.left);                        
            var rightTree = getNodeHeight(node.right);

            var remainder = leftTree - rightTree;
            if( remainder == -2 ){
                // 右子树不平衡
                console.log('右子树不平衡');
                return node;
            }else if( remainder == 2 ){
                // 左子树不平衡
                console.log('左子树不平衡');
                return node;
            }else{
                // 平衡
                var balanceLeft = !node.left ? null : isBalance(node.left);
                var balanceRight = !node.right ? null : isBalance(node.right);

                if( balanceLeft ){
                    return balanceLeft;
                }else if( balanceRight ){
                    return balanceRight;
                }else{
                    return null;    
                }
            }
        }
        // 求出一个节点的高度
        var getNodeHeight = function (node){ 
            if( node == null ){
                return 0;
            }

            var oLeft = getNodeHeight(node.left);

            var oRight = getNodeHeight(node.right);

            return 1+Math.max(oLeft,oRight);
        }

        this.insert = function (key){

            var newNode = new Node(key);

            if( root == null ){
                root = newNode;
            }else{
                insertNode(root,newNode);
            }
        }

        // 中
        this.inOrderTraverse = function(callback){
            inOrderTraverseNode(root,callback);             
        }

        var inOrderTraverseNode = function (node,callback){
            if( node != null ){
                inOrderTraverseNode(node.left,callback);
                callback(node);
                //callback(node);
                inOrderTraverseNode(node.right,callback);
            }
        }

        this.printRoot = function (){
            console.log("根节点为");
            console.log( root );
            console.log( "left Tree -- "+getNodeHeight(root.left) ,'层  right Tree -- '+getNodeHeight(root.right) +"层");
        }

    }
    // Tree 结束 

    var tree = new Tree();  
        //console.log(tree);
        /*tree.insert(1);   
        tree.insert(2);
        tree.insert(3);
        tree.insert(4);
        tree.insert(5);
        tree.insert(6);
        tree.insert(7);
        tree.insert(8);
        tree.insert(9);
        tree.insert(10);
        tree.insert(11);*/

        /*tree.insert(50);
        tree.insert(40);
        tree.insert(45);*/

        /*tree.insert(50);
        tree.insert(40);
        tree.insert(60);
        tree.insert(30);
        tree.insert(45);
        tree.insert(47);*/
        var arr = [50,40,60,30,45,47,5,60,2,334,434,21,32,43,434,367,43];
        for( var i = 0 ; i < arr.length; ++i ){
            tree.insert(arr[i]);
        }

        var printNode = function(value){
            console.log(value,'中序输出');  
        }
        //tree.inOrderTraverse(printNode);

        tree.printRoot();
</script>

结果:图片描述
算法大神请绕道!!!!,本人小白一个

点击查看更多内容
4人点赞

若觉得本文不错,就分享一下吧!

评论

作者其他优质文章

正在加载中
感谢您的支持,我会继续努力的~
扫码打赏,你说多少就多少
赞赏金额会直接到老师账户
支付方式
打开微信扫一扫,即可进行扫码打赏哦
今天注册有机会得

100积分直接送

付费专栏免费学

大额优惠券免费领

立即参与 放弃机会
意见反馈 帮助中心 APP下载
官方微信

举报

0/150
提交
取消