Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: Chapter 10 AVL tree insertNode and removeNode functions #193

Merged
merged 1 commit into from
May 17, 2022
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
45 changes: 19 additions & 26 deletions src/js/data-structures/avl-tree.js
Original file line number Diff line number Diff line change
@@ -101,13 +101,13 @@ export default class AVLTree extends BinarySearchTree {
insertNode(node, key) {
if (node == null) {
return new Node(key);
} if (this.compareFn(key, node.key) === Compare.LESS_THAN) {
}
if (this.compareFn(key, node.key) === Compare.LESS_THAN) {
node.left = this.insertNode(node.left, key);
} else if (this.compareFn(key, node.key) === Compare.BIGGER_THAN) {
node.right = this.insertNode(node.right, key);
} else {
return node; // duplicated key
node.right = this.insertNode(node.right, key);
}

// verify if tree is balanced
const balanceFactor = this.getBalanceFactor(node);
if (balanceFactor === BalanceFactor.UNBALANCED_LEFT) {
@@ -116,7 +116,7 @@ export default class AVLTree extends BinarySearchTree {
node = this.rotationLL(node);
} else {
// Left right case
return this.rotationLR(node);
node = this.rotationLR(node);
}
}
if (balanceFactor === BalanceFactor.UNBALANCED_RIGHT) {
@@ -125,7 +125,7 @@ export default class AVLTree extends BinarySearchTree {
node = this.rotationRR(node);
} else {
// Right left case
return this.rotationRL(node);
node = this.rotationRL(node);
}
}
return node;
@@ -136,32 +136,25 @@ export default class AVLTree extends BinarySearchTree {
if (node == null) {
return node;
}

// verify if tree is balanced
const balanceFactor = this.getBalanceFactor(node);
if (balanceFactor === BalanceFactor.UNBALANCED_LEFT) {
// Left left case
if (
this.getBalanceFactor(node.left) === BalanceFactor.BALANCED
|| this.getBalanceFactor(node.left) === BalanceFactor.SLIGHTLY_UNBALANCED_LEFT
) {
return this.rotationLL(node);
}
// Left right case
if (this.getBalanceFactor(node.left) === BalanceFactor.SLIGHTLY_UNBALANCED_RIGHT) {
return this.rotationLR(node.left);
if (this.compareFn(key, node.left.key) === Compare.LESS_THAN) {
// Left left case
node = this.rotationLL(node);
} else {
// Left right case
node = this.rotationLR(node);
}
}
if (balanceFactor === BalanceFactor.UNBALANCED_RIGHT) {
// Right right case
if (
this.getBalanceFactor(node.right) === BalanceFactor.BALANCED
|| this.getBalanceFactor(node.right) === BalanceFactor.SLIGHTLY_UNBALANCED_RIGHT
) {
return this.rotationRR(node);
}
// Right left case
if (this.getBalanceFactor(node.right) === BalanceFactor.SLIGHTLY_UNBALANCED_LEFT) {
return this.rotationRL(node.right);
if (this.compareFn(key, node.right.key) === Compare.BIGGER_THAN) {
// Right right case
node = this.rotationRR(node);
} else {
// Right left case
node = this.rotationRL(node);
}
}
return node;
108 changes: 34 additions & 74 deletions src/ts/data-structures/avl-tree.ts
Original file line number Diff line number Diff line change
@@ -100,102 +100,62 @@ export default class AVLTree<T> extends BinarySearchTree<T> {
protected insertNode(node: Node<T>, key: T) {
if (node == null) {
return new Node(key);
} else if (this.compareFn(key, node.key) === Compare.LESS_THAN) {
}
if (this.compareFn(key, node.key) === Compare.LESS_THAN) {
node.left = this.insertNode(node.left, key);
} else if (this.compareFn(key, node.key) === Compare.BIGGER_THAN) {
node.right = this.insertNode(node.right, key);
} else {
return node; // duplicated key
node.right = this.insertNode(node.right, key);
}

// verify if tree is balanced
const balanceState = this.getBalanceFactor(node);

if (balanceState === BalanceFactor.UNBALANCED_LEFT) {
const balanceFactor = this.getBalanceFactor(node);
if (balanceFactor === BalanceFactor.UNBALANCED_LEFT) {
if (this.compareFn(key, node.left.key) === Compare.LESS_THAN) {
// Left left case
node = this.rotationLL(node);
} else {
// Left right case
return this.rotationLR(node);
node = this.rotationLR(node);
}
}

if (balanceState === BalanceFactor.UNBALANCED_RIGHT) {
if (balanceFactor === BalanceFactor.UNBALANCED_RIGHT) {
if (this.compareFn(key, node.right.key) === Compare.BIGGER_THAN) {
// Right right case
node = this.rotationRR(node);
} else {
// Right left case
return this.rotationRL(node);
node = this.rotationRL(node);
}
}

return node;
}

protected removeNode(node: Node<T>, key: T) {
if (node == null) {
return null;
}

if (this.compareFn(key, node.key) === Compare.LESS_THAN) {
// The key to be deleted is in the left sub-tree
node.left = this.removeNode(node.left, key);
} else if (this.compareFn(key, node.key) === Compare.BIGGER_THAN) {
// The key to be deleted is in the right sub-tree
node.right = this.removeNode(node.right, key);
} else {
// node is the node to be deleted
if (node.left == null && node.right == null) {
node = null;
} else if (node.left == null && node.right != null) {
node = node.right;
} else if (node.left != null && node.right == null) {
node = node.left;
} else {
// node has 2 children, get the in-order successor
const inOrderSuccessor = this.minNode(node.right);
node.key = inOrderSuccessor.key;
node.right = this.removeNode(node.right, inOrderSuccessor.key);
}
}

if (node == null) {
return node;
}

// verify if tree is balanced
const balanceState = this.getBalanceFactor(node);

if (balanceState === BalanceFactor.UNBALANCED_LEFT) {
// Left left case
if (
this.getBalanceFactor(node.left) === BalanceFactor.BALANCED ||
this.getBalanceFactor(node.left) === BalanceFactor.SLIGHTLY_UNBALANCED_LEFT
) {
return this.rotationLL(node);
}
// Left right case
if (this.getBalanceFactor(node.left) === BalanceFactor.SLIGHTLY_UNBALANCED_RIGHT) {
return this.rotationLR(node.left);
}
}

if (balanceState === BalanceFactor.UNBALANCED_RIGHT) {
// Right right case
if (
this.getBalanceFactor(node.right) === BalanceFactor.BALANCED ||
this.getBalanceFactor(node.right) === BalanceFactor.SLIGHTLY_UNBALANCED_RIGHT
) {
return this.rotationRR(node);
}
// Right left case
if (this.getBalanceFactor(node.right) === BalanceFactor.SLIGHTLY_UNBALANCED_LEFT) {
return this.rotationRL(node.right);
}
}

return node;
node = super.removeNode(node, key); // {1}
if (node == null) {
return node;
}

// verify if tree is balanced
const balanceFactor = this.getBalanceFactor(node);
if (balanceFactor === BalanceFactor.UNBALANCED_LEFT) {
if (this.compareFn(key, node.left.key) === Compare.LESS_THAN) {
// Left left case
node = this.rotationLL(node);
} else {
// Left right case
node = this.rotationLR(node);
}
}
if (balanceFactor === BalanceFactor.UNBALANCED_RIGHT) {
if (this.compareFn(key, node.right.key) === Compare.BIGGER_THAN) {
// Right right case
node = this.rotationRR(node);
} else {
// Right left case
node = this.rotationRL(node);
}
}
return node;
}
}