Node,java
package tree;
public class Node {
public Class<?> clazz;
public Integer value;
public Node parent;
public Node left;
public Node right;
public int height;
public Node(Integer value, Node parent, Node left, Node right) {
this.value = value;
this.parent = parent;
this.left = left;
this.right = right;
}
}
AbstractTree.java
package tree;
public abstract class AbstractTree {
public Node root;
protected Node rotateLeft(Node node) {
Node temp = node.right;
temp.parent = node.parent;
node.right = temp.left;
if (node.right != null) {
node.right.parent = node;
}
temp.left = node;
node.parent = temp;
if (temp.parent == null) {
root = temp;
} else {
if (temp.parent.left == node) {
temp.parent.left = temp;
} else {
temp.parent.right = temp;
}
}
return temp;
}
protected Node rotateRight(Node node) {
Node temp = node.left;
temp.parent = node.parent;
node.left = temp.right;
if (node.left != null) {
node.left.parent = node;
}
temp.right = node;
node.parent = temp;
if (temp.parent == null) {
root = temp;
} else {
if (temp.parent.left == node) {
temp.parent.left = temp;
} else {
temp.parent.right = temp;
}
}
return temp;
}
}
BinarySearchTree.java
package tree;
public class BinarySearchTree extends AbstractTree {
private int size;
public Node insert(int e) {
if (null == root) {
root = new Node(e, null, null, null);
size ++;
return root;
}
Node parent = root;
Node search = root;
while (search != null && search.value != null) {
parent = search;
if (e < search.value) {
search = search.left;
} else {
search = search.right;
}
}
Node newNode = new Node(e, parent, null, null);
if (parent.value > newNode.value) {
parent.left = newNode;
} else {
parent.right = newNode;
}
size ++;
return newNode;
}
public Node search(int e) {
Node node = root;
while (node != null && node.value != null && node.value != e) {
if (e < node.value) {
node = node.left;
} else {
node = node.right;
}
}
return node;
}
public Node delete(int e) {
Node delNode = search(e);
if (null == delNode) {
return null;
}
return delete(delNode);
}
protected Node delete(Node delNode) {
if (delNode == null) {
return null;
}
Node result;
if (delNode.left == null) {
result = transplant(delNode, delNode.right);
} else if (delNode.right == null) {
result = transplant(delNode, delNode.left);
} else {
Node miniNode = getMiniNode(delNode.right);
if (miniNode.parent != delNode) {
transplant(miniNode, miniNode.right);
miniNode.right = delNode.right;
miniNode.right.parent = miniNode;
}
transplant(delNode, miniNode);
miniNode.left = delNode.left;
miniNode.left.parent = miniNode;
result = miniNode;
}
size--;
return result;
}
protected Node getMiniNode(Node node) {
while (node.left != null) {
node = node.left;
}
return node;
}
private Node transplant(Node delNode, Node addNode) {
if (delNode.parent == null) {
this.root = addNode;
} else if (delNode.parent.left == delNode) {
delNode.parent.left = addNode;
} else {
delNode.parent.right = addNode;
}
if (null != addNode) {
addNode.parent = delNode.parent;
}
return addNode;
}
public int getSize() {
return size;
}
}
AVLTree.java
package tree;
public class AVLTree extends BinarySearchTree {
@Override
public Node insert(int e) {
var addNode = super.insert(e);
rebalance(addNode);
return addNode;
}
@Override
public Node delete(int e) {
var delNode = super.search(e);
if (delNode != null) {
var delNodeSuccess = super.delete(delNode);
var min = delNodeSuccess.right != null ? getMiniNode(delNodeSuccess.right) : delNodeSuccess;
recomputeHeight(min);
rebalance(min);
}
return null;
}
private void recomputeHeight(Node node) {
while (node != null) {
node.height = maxHeight(node.left, node.right) + 1;
node = node.parent;
}
}
private int maxHeight(Node node1, Node node2) {
if (node1 != null && node2 != null) {
return node1.height > node2.height ? node1.height : node2.height;
} else if (node1 == null) {
return node2 != null ? node2.height : -1;
} else if (node2 == null) {
return node1 != null ? node1.height : -1;
}
return -1;
}
private void rebalance(Node node) {
while (node != null) {
var parent = node.parent;
var leftHeight = (node.left == null) ? -1 : (node.left).height;
var rightHeight = (node.right == null) ? -1 : (node.right).height;
var factor = leftHeight - rightHeight;
switch (factor) {
case 2:
if (factor(node.left) >= 0) {
var temp = super.rotateRight(node);
refreshHeight(temp.right);
refreshHeight(temp);
} else {
var temp = super.rotateLeft(node.left);
refreshHeight(temp.left);
refreshHeight(temp);
node.left = temp;
temp = super.rotateRight(node);
refreshHeight(temp.right);
refreshHeight(temp);
}
break;
case -2:
if (factor(node.right) <= 0) {
var temp = super.rotateLeft(node);
refreshHeight(temp.left);
refreshHeight(temp);
} else {
var temp = super.rotateRight(node.right);
refreshHeight(temp.right);
refreshHeight(temp);
node.right = temp;
temp = super.rotateLeft(node);
refreshHeight(temp.left);
refreshHeight(temp);
}
break;
default:
refreshHeight(node);
break;
}
node = parent;
}
}
private void refreshHeight(Node node) {
var leftHeight = (node.left == null) ? -1 : (node.left).height;
var rightHeight = (node.right == null) ? -1 : (node.right).height;
node.height = 1 + Math.max(leftHeight, rightHeight);
}
private int factor(Node node) {
var leftHeight = (node.left == null) ? -1 : (node.left).height;
var rightHeight = (node.right == null) ? -1 : (node.right).height;
return leftHeight - rightHeight;
}
}