UNPKG

dsa.js

Version:

Data Structures & Algorithms in JS

174 lines (161 loc) 5.21 kB
// tag::swapParentChild[] /** * Swap parent's child * * @example Child on the left side (it also work for the right side) * * p = parent * o = old child * n = new child * * p p * \ => \ * o n * * @param {TreeNode} oldChild current child's parent * @param {TreeNode} newChild new child's parent * @param {TreeNode} parent parent */ function swapParentChild(oldChild, newChild, parent) { if (parent) { // this set parent child const side = oldChild.isParentRightChild ? 'Right' : 'Left'; parent[`set${side}AndUpdateParent`](newChild); } else { // no parent? so set it to null newChild.parent = null; } } // end::swapParentChild[] // tag::leftRotation[] /** * Single Left Rotation (LL Rotation) * * @example: #1 tree with values 1-2-3-4 * * 1 1 * \ \ * 2* 3 * \ --left-rotation(2)-> / \ * 3 2* 4 * \ * 4 * * @example: #2 left rotation * * 1 1 * \ \ * 4* 16 * / \ / \ * 2 16 -- left-rotation(4) -> 4 32 * / \ / \ \ * 8 32 2 8 64 * \ * 64 * @param {TreeNode} node current node to rotate (e.g. 4) * @returns {TreeNode} new parent after the rotation (e.g. 16) */ function leftRotation(node) { const newParent = node.right; // E.g., node 16 const grandparent = node.parent; // E.g., node 1 const previousLeft = newParent.left; // E.g., node 8 // swap parent of node 4 from node 1 to node 16 swapParentChild(node, newParent, grandparent); // Update node 16 left child to be 4, and // updates node 4 parent to be node 16 (instead of 1). newParent.setLeftAndUpdateParent(node); // set node4 right child to be previousLeft (node 8) node.setRightAndUpdateParent(previousLeft); return newParent; } // end::leftRotation[] // tag::rightRotation[] /** * Single Right Rotation (RR Rotation) * @example: #1 rotate node 3 to the right * * 4 4 * / / * 3* 2 * / / \ * 2 ---| right-rotation(3) |--> 1 3* * / * 1 * * @example: #2 rotate 16 to the right and preserve nodes * 64 64 * / / * 16* 4 * / \ / \ * 4 32 -- right-rotation(16) --> 2 16 * / \ / / \ * 2 8 1 8 32 * / * 1 * * @param {TreeNode} node * this is the node we want to rotate to the right. (E.g., node 16) * @returns {TreeNode} new parent after the rotation (E.g., node 4) */ function rightRotation(node) { const newParent = node.left; // E.g., node 4 const grandparent = node.parent; // E.g., node 64 const previousRight = newParent.right; // E.g., node 8 // swap node 64's left children (node 16) with node 4 (newParent). swapParentChild(node, newParent, grandparent); // update node 4's right child to be node 16, // also make node 4 the new parent of node 16. newParent.setRightAndUpdateParent(node); // Update 16's left child to be the `previousRight` node. node.setLeftAndUpdateParent(previousRight); return newParent; } // end::rightRotation[] // tag::leftRightRotation[] /** * Left Right Rotation (LR Rotation) * * @example LR rotation on node 3 * 4 4 * / / 4 * 3 3* / * / / 2 * 1* --left-rotation(1)-> 2 --right-rotation(3)-> / \ * \ / 1 3* * 2 1 * * @param {TreeNode} node * this is the node we want to rotate to the right. E.g., node 3 * @returns {TreeNode} new parent after the rotation */ function leftRightRotation(node) { leftRotation(node.left); return rightRotation(node); } // end::leftRightRotation[] // tag::rightLeftRotation[] /** * Right Left Rotation (RL Rotation) * * @example RL rotation on 1 * * 1* 1* * \ \ 2 * 3 -right-rotation(3)-> 2 -left-rotation(1)-> / \ * / \ 1* 3 * 2 3 * * @param {TreeNode} node * @returns {TreeNode} new parent after the rotation */ function rightLeftRotation(node) { rightRotation(node.right); return leftRotation(node); } // end::rightLeftRotation[] module.exports = { leftRotation, rightRotation, leftRightRotation, rightLeftRotation, };