我制作了一个包含四个类的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);
}
}