// File: /workspace/github_c_makefile_star2_O0/CarlosLunaMota[P]BinaryTrees/BinaryTrees.c
// Function: bs_tree_rebalance
void bs_tree_rebalance(bs_tree *tree) {

    bs_node *node;
    bs_node *left;
    bs_node *right;
    bs_node *child;
    bs_node *parent;

    // Sanity check:
    assert(tree != NULL);

    // Avoid trivial case: empty tree
    if (tree->root != NULL) {

        // LINEARIZE THE TREE: ///////////////////////////////////
                                                                //
        node = tree->root;                                      //
                                                                //
        // Unravel the left side of root:                       //
        while (node->left != NULL) {                            //
                                                                //
            // Rotate right:                                    //
            left        = node->left;                           //
            right       = left->right;                          //
            left->right = node;                                 //
            node->left  = right;                                //
                                                                //
            // Move to the new root:                            //
            node = left;                                        //
        }                                                       //
                                                                //
        // Fix the root:                                        //
        tree->root = node;                                      //
        parent     = NULL;                                      //
                                                                //
        // Unravel the rest of the tree:                        //
        while (node != NULL) {                                  //
                                                                //
            if (node->left != NULL) {                           //
                                                                //
                // Rotate right:                                //
                left          = node->left;                     //
                right         = left->right;                    //
                left->right   = node;                           //
                node->left    = right;                          //
                parent->right = left;                           //
                                                                //
                // Move up:                                     //
                node = left;                                    //
                                                                //
            } else {                                            //
                                                                //
                // Move down:                                   //
                parent = node;                                  //
                node   = node->right;                           //
            }                                                   //
        }                                                       //
        //////////////////////////////////////////////////////////


        // RE-BALANCE THE TREE ///////////////////////////////////
                                                                //
        for (;;) {                                              //
                                                                //
            parent = NULL;                                      //
            node   = tree->root;                                //
            child  = node->right;                               //
                                                                //
            if (child == NULL) { break; }                       //
                                                                //
            // Move along the right spine:                      //
            while (child != NULL) {                             //
                                                                //
                // Rotate left:                                 //
                if (parent == NULL) { tree->root    = child; }  //
                else                { parent->right = child; }  //
                node->right = child->left;                      //
                child->left = node;                             //
                                                                //
                // Advance:                                     //
                parent = child;                                 //
                node   = parent->right;                         //
                if (node == NULL) { break; }                    //
                else { child = node->right; }                   //
            }                                                   //
        }                                                       //
        //////////////////////////////////////////////////////////


        // A FINAL IMPROVEMENT ///////////////////////////////////
        //
        // When you arrive here the root is the biggest element
        // of the tree and has no right child.
        //
        // So, if we remove the root node and insert it as the
        // right pointer of the second biggest element, the new
        // root element will be way closer to be the "median"
        // element (rather than being the biggest element) and
        // everyone else will be 1 step closer to the root.
        //
        // If you do not understand what I mean, comment the
        // following lines and use the print_bs_tree
        // function to take a look.
        //
        node = tree->root;
        if (node->left != NULL) {
            tree->root = node->left;
            child      = node->left;
            while (child->right != NULL) { child = child->right; }
            child->right = node;
            node->left = NULL;
        }
        //////////////////////////////////////////////////////////
    }
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x30, %rsp
movq %rdi, -0x8(%rbp)
cmpq $0x0, -0x8(%rbp)
je 0xf7b5
jmp 0xf7d4
leaq 0x6ab6(%rip), %rdi      # 0x16272
leaq 0x6a39(%rip), %rsi      # 0x161fc
movl $0x77d, %edx            # imm = 0x77D
leaq 0x6e8a(%rip), %rcx      # 0x16659
callq 0x1060
movq -0x8(%rbp), %rax
cmpq $0x0, (%rax)
je 0xf9b6
movq -0x8(%rbp), %rax
movq (%rax), %rax
movq %rax, -0x10(%rbp)
movq -0x10(%rbp), %rax
cmpq $0x0, 0x8(%rax)
je 0xf832
movq -0x10(%rbp), %rax
movq 0x8(%rax), %rax
movq %rax, -0x18(%rbp)
movq -0x18(%rbp), %rax
movq 0x10(%rax), %rax
movq %rax, -0x20(%rbp)
movq -0x10(%rbp), %rcx
movq -0x18(%rbp), %rax
movq %rcx, 0x10(%rax)
movq -0x20(%rbp), %rcx
movq -0x10(%rbp), %rax
movq %rcx, 0x8(%rax)
movq -0x18(%rbp), %rax
movq %rax, -0x10(%rbp)
jmp 0xf7ed
movq -0x10(%rbp), %rcx
movq -0x8(%rbp), %rax
movq %rcx, (%rax)
movq $0x0, -0x30(%rbp)
cmpq $0x0, -0x10(%rbp)
je 0xf8b3
movq -0x10(%rbp), %rax
cmpq $0x0, 0x8(%rax)
je 0xf89d
movq -0x10(%rbp), %rax
movq 0x8(%rax), %rax
movq %rax, -0x18(%rbp)
movq -0x18(%rbp), %rax
movq 0x10(%rax), %rax
movq %rax, -0x20(%rbp)
movq -0x10(%rbp), %rcx
movq -0x18(%rbp), %rax
movq %rcx, 0x10(%rax)
movq -0x20(%rbp), %rcx
movq -0x10(%rbp), %rax
movq %rcx, 0x8(%rax)
movq -0x18(%rbp), %rcx
movq -0x30(%rbp), %rax
movq %rcx, 0x10(%rax)
movq -0x18(%rbp), %rax
movq %rax, -0x10(%rbp)
jmp 0xf8b1
movq -0x10(%rbp), %rax
movq %rax, -0x30(%rbp)
movq -0x10(%rbp), %rax
movq 0x10(%rax), %rax
movq %rax, -0x10(%rbp)
jmp 0xf845
jmp 0xf8b5
movq $0x0, -0x30(%rbp)
movq -0x8(%rbp), %rax
movq (%rax), %rax
movq %rax, -0x10(%rbp)
movq -0x10(%rbp), %rax
movq 0x10(%rax), %rax
movq %rax, -0x28(%rbp)
cmpq $0x0, -0x28(%rbp)
jne 0xf8dd
jmp 0xf952
jmp 0xf8df
cmpq $0x0, -0x28(%rbp)
je 0xf94d
cmpq $0x0, -0x30(%rbp)
jne 0xf8fa
movq -0x28(%rbp), %rcx
movq -0x8(%rbp), %rax
movq %rcx, (%rax)
jmp 0xf906
movq -0x28(%rbp), %rcx
movq -0x30(%rbp), %rax
movq %rcx, 0x10(%rax)
movq -0x28(%rbp), %rax
movq 0x8(%rax), %rcx
movq -0x10(%rbp), %rax
movq %rcx, 0x10(%rax)
movq -0x10(%rbp), %rcx
movq -0x28(%rbp), %rax
movq %rcx, 0x8(%rax)
movq -0x28(%rbp), %rax
movq %rax, -0x30(%rbp)
movq -0x30(%rbp), %rax
movq 0x10(%rax), %rax
movq %rax, -0x10(%rbp)
cmpq $0x0, -0x10(%rbp)
jne 0xf93f
jmp 0xf94d
movq -0x10(%rbp), %rax
movq 0x10(%rax), %rax
movq %rax, -0x28(%rbp)
jmp 0xf8df
jmp 0xf8b5
movq -0x8(%rbp), %rax
movq (%rax), %rax
movq %rax, -0x10(%rbp)
movq -0x10(%rbp), %rax
cmpq $0x0, 0x8(%rax)
je 0xf9b4
movq -0x10(%rbp), %rax
movq 0x8(%rax), %rcx
movq -0x8(%rbp), %rax
movq %rcx, (%rax)
movq -0x10(%rbp), %rax
movq 0x8(%rax), %rax
movq %rax, -0x28(%rbp)
movq -0x28(%rbp), %rax
cmpq $0x0, 0x10(%rax)
je 0xf99c
movq -0x28(%rbp), %rax
movq 0x10(%rax), %rax
movq %rax, -0x28(%rbp)
jmp 0xf983
movq -0x10(%rbp), %rcx
movq -0x28(%rbp), %rax
movq %rcx, 0x10(%rax)
movq -0x10(%rbp), %rax
movq $0x0, 0x8(%rax)
jmp 0xf9b6
addq $0x30, %rsp
popq %rbp
retq
nopl (%rax)