This commit is contained in:
Joey Eamigh
2023-11-14 18:41:40 -05:00
parent 7b2dc2ac78
commit f1793eafa8
4 changed files with 330 additions and 2 deletions

11
.vscode/launch.json vendored
View File

@@ -6,14 +6,21 @@
"configurations": [
{
"type": "java",
"name": "Main",
"name": "assn06",
"request": "launch",
"mainClass": "assn06.Main",
"projectName": "COMP210_238a5b6"
},
{
"type": "java",
"name": "assn04",
"request": "launch",
"mainClass": "assn04.Main",
"projectName": "COMP210_238a5b6"
},
{
"type": "java",
"name": "Main",
"name": "assn03",
"request": "launch",
"mainClass": "assn03.Main",
"projectName": "COMP210_238a5b6"

203
src/assn06/AVLTree.java Normal file
View File

@@ -0,0 +1,203 @@
package assn06;
public class AVLTree<T extends Comparable<T>> implements SelfBalancingBST<T> {
// Fields
private T _value;
private AVLTree<T> _left;
private AVLTree<T> _right;
private int _height;
private int _size;
public AVLTree() {
_value = null;
_left = null;
_right = null;
_height = -1;
_size = 0;
}
private void updateMeta() {
this._height = 1 + Math.max(this._left.height(), this._right.height());
this._size = 1 + this._left.size() + this._right.size();
}
/**
* Rotates the tree left and returns
* AVLTree root for rotated result.
*/
private AVLTree<T> rotateLeft() {
if (isEmpty())
throw new RuntimeException("Illegal operation on empty tree");
AVLTree<T> newRoot = this._right;
this._right = newRoot._left;
newRoot._left = this;
newRoot._left.updateMeta();
newRoot.updateMeta();
return newRoot;
}
/**
* Rotates the tree right and returns
* AVLTree root for rotated result.
*/
private AVLTree<T> rotateRight() {
if (isEmpty())
throw new RuntimeException("Illegal operation on empty tree");
AVLTree<T> newRoot = this._left;
this._left = newRoot._right;
newRoot._right = this;
newRoot._right.updateMeta();
newRoot.updateMeta();
return newRoot;
}
@Override
public boolean isEmpty() {
return size() == 0;
}
@Override
public int height() {
return _height;
}
@Override
public int size() {
return _size;
}
private int balanceFactor() {
return _left.height() - _right.height();
}
private SelfBalancingBST<T> rebalance() {
AVLTree<T> self = this;
self.updateMeta();
if (self.balanceFactor() > 1)
if (self._left.balanceFactor() < 0) {
self._left = self._left.rotateLeft();
self = self.rotateRight();
} else
self = self.rotateRight();
else if (self.balanceFactor() < -1)
if (self._right.balanceFactor() > 0) {
self._right = self._right.rotateRight();
self = self.rotateLeft();
} else
self = self.rotateLeft();
return self;
}
@Override
public SelfBalancingBST<T> insert(T element) {
if (isEmpty()) {
_value = element;
_left = new AVLTree<T>();
_right = new AVLTree<T>();
_height = 0;
_size = 1;
return this;
}
if (_value.compareTo(element) > 0)
_left = (AVLTree<T>) _left.insert(element);
else if (_value.compareTo(element) < 0)
_right = (AVLTree<T>) _right.insert(element);
return this.rebalance();
}
@Override
public SelfBalancingBST<T> remove(T element) {
if (!contains(element))
return this;
if (_value.compareTo(element) > 0)
_left = (AVLTree<T>) _left.remove(element);
else if (_value.compareTo(element) < 0)
_right = (AVLTree<T>) _right.remove(element);
else {
if (_left.isEmpty() && _right.isEmpty())
return new AVLTree<T>();
else if (_left.isEmpty())
return _right;
else if (_right.isEmpty())
return _left;
else {
_value = _right.findMin();
_right = (AVLTree<T>) _right.remove(_value);
}
}
return this.rebalance();
}
@Override
public T findMin() {
if (isEmpty()) {
throw new RuntimeException("Illegal operation on empty tree");
}
if (_left.isEmpty()) {
return _value;
} else {
return _left.findMin();
}
}
@Override
public T findMax() {
if (isEmpty()) {
throw new RuntimeException("Illegal operation on empty tree");
}
if (_right.isEmpty()) {
return _value;
} else {
return _right.findMax();
}
}
@Override
public boolean contains(T element) {
if (isEmpty())
return false;
if (_value.compareTo(element) == 0)
return true;
else if (_value.compareTo(element) > 0)
return _left.contains(element);
else
return _right.contains(element);
}
@Override
public T getValue() {
return _value;
}
@Override
public SelfBalancingBST<T> getLeft() {
if (isEmpty()) {
return null;
}
return _left;
}
@Override
public SelfBalancingBST<T> getRight() {
if (isEmpty()) {
return null;
}
return _right;
}
}

42
src/assn06/Main.java Normal file
View File

@@ -0,0 +1,42 @@
package assn06;
public class Main {
public static void main(String[] args) {
// Create a new empty tree.
SelfBalancingBST<Integer> avl_bst = new AVLTree<Integer>();
// Insert 50 random integers.
// Note how we need to capture the result of insert back into
// the variable avl_bst because the post-insertion root that is
// returned may be different from the original root because of the insertion.
// result should be about 6.
for (int i = 0; i < 50; i++) {
int rand = (int) (Math.random() * 100);
while (avl_bst.contains(rand))
rand = (int) (Math.random() * 100);
avl_bst = avl_bst.insert(rand);
}
System.out.println("\nheight: " + avl_bst.height());
System.out.println("size: " + avl_bst.size());
// Now insert 50 integers in increasing order which would
// cause a simple BST to become very tall but for our
// self-balancing tree won't be too bad (should be 7)
for (int i = 150; i < 200; i++) {
avl_bst = avl_bst.insert(i);
}
System.out.println("\nheight: " + avl_bst.height());
System.out.println("size: " + avl_bst.size());
// test remove
avl_bst = avl_bst.remove(avl_bst.findMax());
avl_bst = avl_bst.remove(avl_bst.findMin());
System.out.println("\nheight: " + avl_bst.height());
System.out.println("size: " + avl_bst.size());
}
}

View File

@@ -0,0 +1,76 @@
package assn06;
public interface SelfBalancingBST<T extends Comparable<T>> {
/**
* @return true if the tree is empty
*/
boolean isEmpty();
/**
* @return height of the tree.
*/
int height();
/**
* @return the number of elements in the tree
*/
int size();
/**
* Inserts element into tree and returns resulting
* tree (i.e. root) after insertion. Depending on implementation,
* this may or may not be the same object that you started with.
* @param element to be added to the tree
* @return resulting tree after insertion
**/
SelfBalancingBST<T> insert(T element);
/**
* Removes element from tree and returns resulting
* tree after removal. Depending on implementation,
* this may or may not be the same object that you
* started with. If element is not in the tree, the
* tree should remain unchanged and return itself.
* @param element to be removed from the tree
* @return resulting tree after removal
**/
SelfBalancingBST<T> remove(T element);
/**
* Throws a RuntimeException if called on an empty tree.
* @return the smallest value in the tree
*/
T findMin();
/**
* Throws a RuntimeException if called on an empty tree.
* @return the smallest value in the tree.
*/
T findMax();
/**
* @param element whose presence in this tree is to be tested
* @return true if this tree contains the specified element
*/
boolean contains(T element);
/**
* @return value at the top of the tree.
* If a tree is empty, its value is null.
*/
T getValue();
/**
* @return the left child of the tree.
* Throws a RuntimeException if the tree is empty.
*/
SelfBalancingBST<T> getLeft();
/**
* @return the right child of the tree.
* Throws a RuntimeException if the tree is empty.
*/
SelfBalancingBST<T> getRight();
}