zoukankan      html  css  js  c++  java
  • 14.非平衡树的双旋(左右双旋和右左双旋和右右双旋和左左双旋)代码实现(JavaScript版)

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>Document</title>
    </head>
    <body>
        <script>
            //非平衡二叉树的双旋(左右双旋,右左双旋)
            //当要对某个节点进行左单旋时,若变化分支是唯一的最深分支,那么要对新根进行右单旋,然后在进行左单旋,这样的旋转叫做右左双旋
            //当要对某个节点进行右单旋时,若变化分支是唯一的最深分支,那么要对新根进行左单旋,然后在进行右单旋,这样的旋转叫做左右双旋
            function Node(value) {
                this.value = value;
                this.left = null;
                this.right = null;
            }
    
            var node1 = new Node(1);
            var node2 = new Node(2);
            var node3 = new Node(3);
            var node4 = new Node(4);
            var node5 = new Node(5);
            var node6 = new Node(6);
            
            node6.left = node3;
            node3.left = node2;
            node2.left = node1;
            node3.right = node4;
            node4.right = node5;
    
            function isBalance(root){//判断二叉树是否平衡
                if(root == null) return true;
                var leftDeep = getDeep(root.left);
                var rightDeep = getDeep(root.right);
                if(Math.abs(leftDeep - rightDeep) > 1){//左右深度相差大于1,则不平衡
                    return false
                }else{
                    //判断左右子树是否平衡
                    return isBalance(root.left) && isBalance(root.right);
                }
            }
    
            //获取树的深度
            function getDeep(root){
                if(root == null) return 0;
                var leftDeep = getDeep(root.left);//获取左子树深度
                var rightDeep = getDeep(root.right);//获取右子树深度
                return Math.max(leftDeep, rightDeep) + 1;//左右子树深度最大的值 + 1;
            }
    
            //非平衡树要旋转,变成平衡树
            function change(root){
                if(isBalance(root)) return root;//树平衡了,返回该树
                if(root.left != null) root.left = change(root.left);//把左子树变为平衡树
                if(root.right != null) root.right = change(root.right);//把右子树变成平衡树
                var leftDeep = getDeep(root.left);
                var rightDeep = getDeep(root.right);
                if(Math.abs(leftDeep - rightDeep) < 2){
                    return root;
                }else if(leftDeep > rightDeep){//左深右浅,要右旋
                    var changeTreeDeep = getDeep(root.left.right);//变化分支的深度
                    var noChangeTreeDeep = getDeep(root.left.left);//不变化分支的深度
                    if(changeTreeDeep > noChangeTreeDeep    ){//变化分支深度 大于 不变化分支深度,要将左子树先进行左旋
                        root.left = leftRotate(root.left);
                    }
                    var newRoot =  rightRotate(root);//右旋,右旋是为了减小左子树深度,但是右旋后可能增加右子树深度
                    newRoot = change(newRoot);//右旋后可能会导致树不平衡,所以再次平衡
    
                    return newRoot;
                }else{//左浅右深,要左旋
                    var changeTreeDeep = getDeep(root.right.left);//变化分支的深度
                    var noChangeTreeDeep = getDeep(root.right.right);//不变化分支的深度
                    if(changeTreeDeep > noChangeTreeDeep){//变化分支深度 大于 不变化分支深度,要将右子树先进行右旋
                        root.right = rightRotate(root.right);
                    }
                    var newRoot = leftRotate(root);//左旋,左旋是为了减小右子树深度,但是左旋后可能增加左子树深度
                    newRoot = change(newRoot);//左旋后可能会导致树不平衡,所以再次平衡
    
                    return newRoot;
                }
            }
    
            //左旋
            function leftRotate(root){
                //找到新根
                var newRoot = root.right;
                //找到变化的分支
                var changeTree = root.right.left;
                //将当前节点赋值到新根的左节点
                newRoot.left = root;
                //将变化分支赋值到当前节点的右节点
                root.right = changeTree;
                
                return newRoot;//返回新根
            }
    
            //右旋
            function rightRotate(root){
                //找到新根
                var newRoot = root.left;
                //找到变化的分支
                var changeTree = root.left.right;
                //将当前节点赋值到新根的右节点
                newRoot.right = root;
                //将变化分支赋值到当前节点的左节点
                root.left = changeTree;
                
                return newRoot;//返回新根
            }
    
            console.log(isBalance(node6));
            var newRoot = change(node6);
            console.log(isBalance(newRoot));
            console.log(newRoot);
        </script>
    </body>
    </html>
    非平衡树的双旋
  • 相关阅读:
    《算法竞赛进阶指南》0x12 队列 POJ2259 Team Queue
    《算法竞赛进阶指南》0x11栈 单调栈求矩形面积 POJ2559
    《算法竞赛进阶指南》0x11 栈 求解中缀表达式
    19.职责链模式(Chain of Responsibility Pattern)
    16.观察者模式(Observer Pattern)
    17.解释器模式(Interpreter Pattern)
    15. 迭代器模式(Iterator Pattern)
    14.命令模式(Command Pattern)
    12.代理模式(Proxy Pattern)
    13.模板方法(Template Method)
  • 原文地址:https://www.cnblogs.com/lanshanxiao/p/13205320.html
Copyright © 2011-2022 走看看