JAVA - 更新来自不同类的变量

时间:2017-03-02 12:57:44

标签: java data-structures avl-tree

我制作了一个包含四个类的AVL树,如下面的代码所示。我在旋转之后遇到问题以平衡树,当实际根可能在旋转后改变时,在我的情况下它永远不会改变。它仍然是我第一次插入root的价值。因此,我无法正确插入位置或正确执行打印操作,因为这两种方法都以root作为参数。

我调试了代码。旋转方法正确执行旋转。

我的问题是,每当旋转将树的根更改为其他节点(值)时,如何将树的根更新为新根?

CODE:

/* P: parent node of treeNode(Node)
* lc: left child node of treeNode(Node)
* rc: right child node of treeNode(Node)
*/
class AVl_exp{
static Scanner sc = new Scanner(System.in);
static boolean perform_another_operation = true;
public static void main(String[] args){

    TreeOperation<Integer> op = new TreeOperation<>();

    //Insert at root, when tree is empty.
    System.out.println("The tree is empty. Insert At root.");
    MyLinkNode<Integer> start = op.insertAtRoot();
    int x=0;

    //Ask user for operation he would like to perform on the list.
    do{
        System.out.println("What Operation would you like to perform on the tree?");
        x = sc.nextInt();

        switch(x){
            case 1: {op.insertNode(start.root);break;}
            case 2: {op.printTree(start.root);break;}
            default: break;
        }
    }while(perform_another_operation == performOrNot());
}

private static boolean performOrNot() {
    System.out.println("\nWould you like to perform another list operation. Type in true or false. \n");
    perform_another_operation = sc.nextBoolean();
    return perform_another_operation;
}

}

class MyLinkNode<E extends Comparable<E>>{
TreeNode<E> root;
static int Height_Of_Tree = 0;
static boolean Tree_Empty = true;

//Create and update Root Node. Initial call from TreeOperation's insertAtRoot method.
MyLinkNode(E x){
    root = new TreeNode<>();
    root.parent = null;
    root.leftnode = null;
    root.rightnode = null;
    root.nodeHeight = 0;
    root.val = x;
}

public MyLinkNode() {}

}

class TreeNode<E extends Comparable<E>> {
TreeNode<E> parent; 
TreeNode<E> leftnode;
TreeNode<E> rightnode;
E val;
int nodeHeight;
int rightNullHeight = -1;
int leftNullHeight = -1;

TreeNode(){};

TreeNode(TreeNode<E> prev, E x){
    this.val = x;
    this.parent = prev;
    this.rightnode = null;
    this.leftnode = null;
    this.nodeHeight = 0;

    //if-else to update parent's leftnode or rightnode pointer accordingly.
    if(x.compareTo(prev.val) < 0){
        prev.leftnode = this;
        prev.leftNullHeight = 0;
    }
    else{
        prev.rightnode = this;
        prev.rightNullHeight = 0;
    }

    RotateAndUpdateHeight(this);
}

private void RotateAndUpdateHeight(TreeNode<E> treeNode) {

    if(treeNode.parent != null){//This if condition check is required to check
        //NullPointer Exception that may arise if recursion stack calls  
        //RotateAndUpdateHeight(TreeNode<E> treeNode) with root as argument, in which case
        //a call like treeNode.parent.leftnode will throw the exception.

        //takes care of cases when Node's parent is complete.
        if(treeNode.parent.leftnode != null && treeNode.parent.rightnode != null){
            int height_diff = Math.abs(treeNode.parent.leftnode.nodeHeight - 
                                        treeNode.parent.rightnode.nodeHeight);
            if(height_diff > 1){
                performRotation(treeNode);
            }
            else{//Increase height up to P Node only if the tree is balanced from leaf to P.
                 //In case an imbalance is encountered on the way, height only up to Node(treeNode) is
                 //incremented and then performRotation method is called from recursion stack with Node(treeNode).
                 //Specifically mentioned because in schematic construction of AVL tree, height of P is incremented
                 //in all cases.
                treeNode.parent.nodeHeight++;
                RotateAndUpdateHeight(treeNode.parent);
            }
        }

        //takes care of cases when Node's parent has a null node(either parent.leftnode == null 
        //or parent.rightnode == null)
        else if((treeNode.parent.leftnode == null || treeNode.parent.rightnode == null)){
            int height_diff = Math.abs(treeNode.nodeHeight - (-1));
            if(height_diff > 1){
                performRotation(treeNode);
            }
            else{//Increase height up to P Node only if the tree is balanced from leaf to P.
                 //In case an imbalance is encountered on the way, height only up to Node(treeNode) is
                 //incremented and then performRotation method is called from recursion stack with Node(treeNode).
                 //Specifically mentioned because in schematic construction of AVL tree, height of P is incremented
                 //in all cases.
                treeNode.parent.nodeHeight++;
                RotateAndUpdateHeight(treeNode.parent);
            }
        }

        else{
            return;
        }
    }
}

private void performRotation(TreeNode<E> treeNode) {

    if(treeNode.rightnode != null){//This if condition check is required to check
        //NullPointerException that may arise in cases where Node's right child don't exist.
        if(treeNode.val.compareTo(treeNode.parent.val) > 0 && 
                treeNode.val.compareTo(treeNode.rightnode.val) < 0){
            performLRparent(treeNode);
        }
        else if(treeNode.val.compareTo(treeNode.parent.val) < 0 &&
                treeNode.val.compareTo(treeNode.rightnode.val) < 0){
            performLRnode_RRparent(treeNode);
        }
    }
    else{
        if(treeNode.val.compareTo(treeNode.parent.val) < 0 &&
                treeNode.val.compareTo(treeNode.leftnode.val) > 0){
            performRRparent(treeNode);
        }
        else if(treeNode.val.compareTo(treeNode.parent.val) > 0 &&
                treeNode.val.compareTo(treeNode.leftnode.val) > 0){
            performRRnode_LRparent(treeNode);
        }
    }
}

private void performLRparent(TreeNode<E> treeNode) {
    treeNode.parent.rightnode = null;//make P rightnode = null.
    treeNode.parent.rightNullHeight = -1;//update rightNullHeight of P.
    treeNode.leftnode = treeNode.parent;//make P left child of Node.
    treeNode.leftNullHeight = 0;//update Node leftNullHeight.
    treeNode.parent = treeNode.parent.parent;//make parent of P, parent of Node.
    treeNode.leftnode.parent = treeNode;//make Node, parent of P.
}

private void performRRparent(TreeNode<E> treeNode) {
    treeNode.parent.leftnode = null;//Make P leftnode = null.
    treeNode.parent.leftNullHeight = -1;//update leftNullHeight of P.
    treeNode.rightnode = treeNode.parent;//Make P right child of Node.
    treeNode.rightNullHeight = 0;//update Node rightNullHeight.
    treeNode.parent = treeNode.parent.parent;//make parent of P, parent of Node.
    treeNode.rightnode.parent = treeNode;//make Node parent of P.
}

private void performRRnode_LRparent(TreeNode<E> treeNode){
    //update nodeHeights
    treeNode.nodeHeight = treeNode.nodeHeight - 1;
    treeNode.parent.nodeHeight = treeNode.parent.nodeHeight - 1;
    treeNode.leftnode.nodeHeight = treeNode.leftnode.nodeHeight + 1;

    boolean B_Exists = false;
    //take care of B node. B is left child node of lc.
    if(treeNode.leftnode.leftnode != null){
        treeNode.leftnode.leftnode.parent = treeNode.parent;//make P parent of B.
        treeNode.parent.rightnode = treeNode.leftnode.leftnode;//make B right child of P.
        B_Exists = true;
        treeNode.parent.rightNullHeight = 0;//As B exists, update P rightNullHeight.
    }
    //Manipulate the links in the main spine, i.e P, Node, lc.

    treeNode.leftnode.parent = treeNode.parent.parent;//make P's parent, parent of lc.

    //Change relation b/w P and lc.
    treeNode.leftnode.leftnode = treeNode.parent;//make lc parent of P.
    treeNode.parent.parent = treeNode.leftnode;//make P left child of lc.
    treeNode.parent.parent.leftNullHeight = 0;//update lc's leftNullHeight.

    if(B_Exists == false){
        treeNode.parent.rightnode = null;
        treeNode.parent.rightNullHeight = -1;//update P rigthNullHeight.
    }

    //take care of C node. C is right child node of lc.
    boolean C_Exists = false;
    if(treeNode.leftnode.rightnode != null){
        treeNode.leftnode.rightnode.parent = treeNode;//make Node parent C.
        treeNode.leftnode = treeNode.leftnode.rightnode;//make C left child of Node.
        C_Exists = true;
        treeNode.leftNullHeight = 0;//As B exists, update Node leftNullHeight.
    }

    //Change relation b/w Node and lc.
    treeNode.parent = treeNode.parent.parent;//make lc parent of P.
    treeNode.parent.rightnode = treeNode;//make Node right child of P. 
    treeNode.parent.rightNullHeight = 0;//update lc's rightNullHeight.

    //Make Node's leftnode == null if C does not exist.
    if(C_Exists == false){
        treeNode.leftnode = null;
        treeNode.leftNullHeight = -1;//update Node leftNullHeight.
    }
}

private void performLRnode_RRparent(TreeNode<E> treeNode){
    //update nodeHeights
    treeNode.nodeHeight = treeNode.nodeHeight - 1;
    treeNode.parent.nodeHeight = treeNode.parent.nodeHeight - 1;
    treeNode.rightnode.nodeHeight = treeNode.rightnode.nodeHeight + 1;

    boolean Rotation_Changes_Current_Root = false;
    if(treeNode.parent.parent == null){
        Rotation_Changes_Current_Root = true;
    }

    //take care of C node. C is right chil node of rc.
    boolean C_Exists = false;
    if(treeNode.rightnode.rightnode != null){
        treeNode.rightnode.rightnode.parent = treeNode.parent;//make P parent of C.
        treeNode.parent.leftnode = treeNode.rightnode.rightnode;//make C left child of P.
        C_Exists = true;
        treeNode.parent.leftNullHeight = 0;//As C exists, update P leftNullHeight.
    }

    //--------Manipulate the links in the main spine, i.e P, Node, rc.--------

    treeNode.rightnode.parent = treeNode.parent.parent;//make parent of P, parent of rc.

    //Change relation b/w P and rc.
    treeNode.parent.parent = treeNode.rightnode;//make rc parent of P.
    treeNode.rightnode.rightnode = treeNode.parent;//make P right child of rc.
    treeNode.parent.parent.rightNullHeight = 0;//update rc's rigthNullHeight.

    if(C_Exists == false){
        treeNode.parent.leftnode = null;
        treeNode.parent.leftNullHeight = -1;//update P leftNullHeight only if C does not exist.
    }

    //take care of B node. B is left child node of rc.
    boolean B_Exists = false;

    if(treeNode.rightnode.leftnode != null){
        treeNode.rightnode.leftnode.parent = treeNode;//make Node parent of B.
        treeNode.rightnode = treeNode.rightnode.leftnode;//make B right child of Node.
        treeNode.rightNullHeight = 0;//update Node rightNullHeight if B exist.
        B_Exists = true;
    }

    //Change relation b/w Node and rc.
    treeNode.parent = treeNode.parent.parent;//Make lc parent of Node.
    treeNode.parent.leftnode = treeNode;//make Node left child of rc.
    treeNode.parent.leftNullHeight = 0;//update rc's leftNullHeight.

    //Now make Node rightnode == null if B does not exist.
    if(B_Exists == false){
        treeNode.rightnode = null;
        treeNode.rightNullHeight = -1;//update Node rightNullHeight.
    }
}

}

class TreeOperation<E extends Comparable<E>>{

TreeOperation(){};
static Scanner sc = new Scanner(System.in);

MyLinkNode<Integer> insertAtRoot(){
    System.out.println("Enter the Integer value you want to add in the tree.");
    int x = sc.nextInt();
    return new MyLinkNode<Integer>(x);
}

//Insert new nodes.
void insertNode(TreeNode<Integer> root){
    System.out.println("Enter the Integer value you want to add in the tree.");
    int x = sc.nextInt();
    TreeNode<Integer> stub = traverse(root, x);
    new TreeNode<>(stub, x);
}

//Traverse to the appropriate position in the tree to insert node.
private TreeNode<Integer> traverse(TreeNode<Integer> stub, int x){
    while(stub.leftnode != null || stub.rightnode != null){
        if(stub.leftnode != null && x < stub.val){
            stub = stub.leftnode;
        }
        else if(stub.rightnode != null && x > stub.val)
            stub = stub.rightnode;
        else{
            if(stub.leftnode == null && x < stub.val){
                return stub;
            }
            else{
                return stub;
            }
        }
    }
    return stub;
}

//Print tree nodes via InOrder traversal.
void printTree(TreeNode<E> stub){ //In-order Traversal

        if (stub == null)
            return;

        /* first recur on left child */
        printTree(stub.leftnode);

        /* then print the data of node */
        System.out.print(stub.val + " ");

        /* now recur on right child */
        printTree(stub.rightnode);

}

}

0 个答案:

没有答案