From f0fa8e52646200cb026831aefcf0390dcae41a26 Mon Sep 17 00:00:00 2001 From: Jeff Zhang <72734421+jeff-zhenz@users.noreply.github.com> Date: Tue, 17 May 2022 18:16:35 +0800 Subject: [PATCH] fix: AVL tree insertNode and removeNode functions --- src/js/data-structures/avl-tree.js | 45 +++++------- src/ts/data-structures/avl-tree.ts | 108 +++++++++-------------------- 2 files changed, 53 insertions(+), 100 deletions(-) diff --git a/src/js/data-structures/avl-tree.js b/src/js/data-structures/avl-tree.js index 8ea3cfb9..6b4ee7c0 100644 --- a/src/js/data-structures/avl-tree.js +++ b/src/js/data-structures/avl-tree.js @@ -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; diff --git a/src/ts/data-structures/avl-tree.ts b/src/ts/data-structures/avl-tree.ts index feb44a19..266e204a 100644 --- a/src/ts/data-structures/avl-tree.ts +++ b/src/ts/data-structures/avl-tree.ts @@ -100,102 +100,62 @@ export default class AVLTree extends BinarySearchTree { protected insertNode(node: Node, 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, 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; } }