Skip to content

Commit afa4948

Browse files
committed
Simplify AVL tree node deletion.
1 parent 04e533e commit afa4948

File tree

2 files changed

+72
-87
lines changed

2 files changed

+72
-87
lines changed

src/data-structures/tree/avl-tree/AvlTree.js

Lines changed: 5 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -16,54 +16,16 @@ export default class AvlTree extends BinarySearchTree {
1616
}
1717
}
1818

19-
remove(value) {
20-
const nodeToRemove = this.root.find(value);
21-
22-
if (!nodeToRemove) {
23-
throw new Error('Item not found in the tree');
24-
}
25-
26-
// Recursively find target node, if found then delete and balance.
27-
// return nodeToRemove.value;
28-
this.root = this.removeRecv(this.root, nodeToRemove);
29-
}
30-
31-
removeRecv(origin, node) {
32-
let newOrigin = origin;
33-
if (origin.value > node.value) {
34-
// Recursively traversing from left
35-
newOrigin.left = this.removeRecv(origin.left, node);
36-
} else if (origin.value < node.value) {
37-
// Recursively traversing from right
38-
newOrigin.right = this.removeRecv(origin.right, node);
39-
} else {
40-
if (origin.left == null) {
41-
// Forget right node
42-
return origin.right;
43-
}
44-
if (origin.right == null) {
45-
// Forget left node
46-
return origin.left;
47-
}
48-
49-
// Recursively find min node from left subtree
50-
// more efficient traversing
51-
const parent = Object.assign({}, origin);
52-
newOrigin = parent.right.findMin();
53-
newOrigin.right = this.deleteMin(parent.right);
54-
newOrigin.left = parent.left;
55-
}
56-
57-
// Balance and return root node
58-
return this.balance(newOrigin);
59-
}
60-
6119
/**
6220
* @param {*} value
6321
* @return {boolean}
6422
*/
6523
remove(value) {
66-
throw new Error(`Can't remove ${value}. Remove method is not implemented yet`);
24+
// Do standard BST removal.
25+
super.remove(value);
26+
27+
// Balance the tree starting from the root node.
28+
this.balance(this.root);
6729
}
6830

6931
/**
@@ -90,8 +52,6 @@ export default class AvlTree extends BinarySearchTree {
9052
this.rotateRightLeft(node);
9153
}
9254
}
93-
// Return the heap to avoid referenceError
94-
return node;
9555
}
9656

9757
/**
@@ -200,15 +160,4 @@ export default class AvlTree extends BinarySearchTree {
200160
// Attach rootNode to the left of rightNode.
201161
rightNode.setLeft(rootNode);
202162
}
203-
204-
deleteMin(node) {
205-
// Forget right node if has value
206-
if (node.left == null) return node.right;
207-
208-
const newNode = node;
209-
newNode.left = this.deleteMin(node.left);
210-
211-
// Balance and return root node
212-
return this.balance(newNode);
213-
}
214163
}

src/data-structures/tree/avl-tree/__test__/AvlTRee.test.js

Lines changed: 67 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -186,31 +186,6 @@ describe('AvlTree', () => {
186186
expect(tree.toString()).toBe('6,8,9,18,21,22,43');
187187
});
188188

189-
it('should keep balance after removal', () => {
190-
const tree = new AvlTree();
191-
192-
tree.insert(1);
193-
tree.insert(2);
194-
tree.insert(3);
195-
tree.insert(4);
196-
tree.insert(5);
197-
tree.insert(6);
198-
tree.insert(7);
199-
tree.insert(8);
200-
tree.insert(9);
201-
202-
expect(tree.toString()).toBe('1,2,3,4,5,6,7,8,9');
203-
expect(tree.root.height).toBe(3);
204-
205-
tree.remove(8);
206-
tree.remove(9);
207-
208-
expect(tree.contains(8)).toBeFalsy();
209-
expect(tree.contains(9)).toBeFalsy();
210-
expect(tree.toString()).toBe('1,2,3,4,5,6,7');
211-
expect(tree.root.height).toBe(2);
212-
});
213-
214189
it('should do left right rotation and keeping left right node safe', () => {
215190
const tree = new AvlTree();
216191

@@ -255,13 +230,74 @@ describe('AvlTree', () => {
255230
expect(tree.root.height).toBe(3);
256231
});
257232

258-
it('should throw an error when trying to remove the node', () => {
259-
const removeNodeAvlTree = () => {
260-
const tree = new AvlTree();
233+
it('should remove values from the tree with right-right rotation', () => {
234+
const tree = new AvlTree();
235+
236+
tree.insert(10);
237+
tree.insert(20);
238+
tree.insert(30);
239+
tree.insert(40);
240+
241+
expect(tree.toString()).toBe('10,20,30,40');
242+
243+
tree.remove(10);
244+
245+
expect(tree.toString()).toBe('20,30,40');
246+
expect(tree.root.value).toBe(30);
247+
expect(tree.root.left.value).toBe(20);
248+
expect(tree.root.right.value).toBe(40);
249+
expect(tree.root.balanceFactor).toBe(0);
250+
});
251+
252+
it('should remove values from the tree with left-left rotation', () => {
253+
const tree = new AvlTree();
254+
255+
tree.insert(10);
256+
tree.insert(20);
257+
tree.insert(30);
258+
tree.insert(5);
259+
260+
expect(tree.toString()).toBe('5,10,20,30');
261+
262+
tree.remove(30);
263+
264+
expect(tree.toString()).toBe('5,10,20');
265+
expect(tree.root.value).toBe(10);
266+
expect(tree.root.left.value).toBe(5);
267+
expect(tree.root.right.value).toBe(20);
268+
expect(tree.root.balanceFactor).toBe(0);
269+
});
270+
271+
it('should keep balance after removal', () => {
272+
const tree = new AvlTree();
273+
274+
tree.insert(1);
275+
tree.insert(2);
276+
tree.insert(3);
277+
tree.insert(4);
278+
tree.insert(5);
279+
tree.insert(6);
280+
tree.insert(7);
281+
tree.insert(8);
282+
tree.insert(9);
283+
284+
expect(tree.toString()).toBe('1,2,3,4,5,6,7,8,9');
285+
expect(tree.root.value).toBe(4);
286+
expect(tree.root.height).toBe(3);
287+
expect(tree.root.balanceFactor).toBe(-1);
288+
289+
tree.remove(8);
261290

262-
tree.remove(1);
263-
};
291+
expect(tree.root.value).toBe(4);
292+
expect(tree.root.balanceFactor).toBe(-1);
293+
294+
tree.remove(9);
264295

265-
expect(removeNodeAvlTree).toThrowError();
296+
expect(tree.contains(8)).toBeFalsy();
297+
expect(tree.contains(9)).toBeFalsy();
298+
expect(tree.toString()).toBe('1,2,3,4,5,6,7');
299+
expect(tree.root.value).toBe(4);
300+
expect(tree.root.height).toBe(2);
301+
expect(tree.root.balanceFactor).toBe(0);
266302
});
267303
});

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy