UNPKG

compound-binary-file-js

Version:

This is an implementation of [Compound Binary File v.3](https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-cfb/53989ce4-7b05-4f8d-829b-d08d6148375b) \ Allows reading existing files, creation of the/write operation

176 lines (168 loc) 7.51 kB
import {UpdateHandler} from "./UpdateHandler"; import {Color, TreeNode} from "./Node"; import {RedBlackTree} from "./RedBlackTree"; export class DeleteHandler<T> extends UpdateHandler<T> { private readonly comparator: (o1: T, o2: T) => number; constructor(tree: RedBlackTree<T>, comparator: (o1: T, o2: T) => number) { super(tree); this.comparator = comparator; } delete(node: TreeNode<T>): void { if(!node.hasChildren()) { if(this.tree.isRoot(node)) { this.tree.setRoot(null); } else { if (node.getColor() === Color.BLACK) { const sibling = node.sibling(); node.getParent().deleteChild(node); this.recover(sibling); } else { node.getParent().deleteChild(node); } } } else if(node.hasTwoChildren()) { const substituteWith = this.inOrderPredecessor(node); this.swap(node, substituteWith); this.delete(node); } else { let substituteWith; if(node.getRightChild() == null) { substituteWith = node.getLeftChild(); } else { substituteWith = node.getRightChild(); } if(this.tree.isRoot(node)) { this.tree.setRoot(substituteWith); substituteWith.setColor(Color.BLACK); } else if(substituteWith.getColor() === Color.RED || node.getColor() === Color.RED) { node.getParent().substituteNode(node, substituteWith); substituteWith.setColor(Color.BLACK); } else { const sibling = node.sibling(); node.getParent().substituteNode(node, substituteWith); this.recover(sibling); } } } inOrderPredecessor(node: TreeNode<T>): TreeNode<T> { if(node.getLeftChild() == null) { return null; } else { const allChildren = node.getLeftChild().getChildrenRecursive(); allChildren.push(node.getLeftChild()); allChildren.sort((a: TreeNode<T>, b: TreeNode<T>) => this.comparator(a.getValue(), b.getValue())); return allChildren[allChildren.length - 1]; } } recover(sibling: TreeNode<T>): void { const siblingColor = sibling.getColor(); const siblingsLeftChild = sibling.getLeftChild(); const siblingsRightChild = sibling.getRightChild(); const siblingLeftChildColor = siblingsLeftChild == null ? Color.BLACK : siblingsLeftChild.getColor(); const siblingRightChildColor = siblingsRightChild == null ? Color.BLACK : siblingsRightChild.getColor(); const isSiblingLeftChild = sibling.getParent().isLeftChild(sibling); if(siblingColor === Color.BLACK) { if(siblingLeftChildColor === Color.RED || siblingRightChildColor === Color.RED) { if(sibling.getParent().isLeftChild(sibling)) { if(siblingLeftChildColor === Color.RED) { this.rightRotate(sibling.getParent(), sibling); siblingsLeftChild.setColor(Color.BLACK); } else { this.leftRotate(sibling, sibling.getRightChild()); this.rightRotate(sibling.grandParent(), sibling.getParent()); sibling.setColor(Color.BLACK); } } else { if(siblingRightChildColor === Color.RED) { this.leftRotate(sibling.getParent(), sibling); siblingsRightChild.setColor(Color.BLACK); } else { this.rightRotate(sibling, sibling.getLeftChild()); this.leftRotate(sibling.grandParent(), sibling.getParent()); sibling.setColor(Color.BLACK); } } } else { sibling.setColor(Color.RED); const parent = sibling.getParent(); if(parent.getColor() === Color.BLACK && !this.tree.isRoot(parent)) { this.recover(parent.sibling()); } else { parent.setColor(Color.BLACK); } } } else { const parent = sibling.getParent(); let newSibling; sibling.setColor(Color.BLACK); parent.setColor(Color.RED); if(isSiblingLeftChild) { newSibling = sibling.getRightChild(); this.rightRotate(sibling.getParent(), sibling); } else { newSibling = sibling.getLeftChild(); this.leftRotate(sibling.getParent(), sibling); } this.recover(newSibling); } } swap(node1: TreeNode<T>, node2: TreeNode<T>): void { if(node1.getParent() === node2) { this.swapChildParent(node2, node1); } else if(node2.getParent() === node1) { this.swapChildParent(node1, node2); } else { const node1Parent = node1.getParent(); const node1LeftChild = node1.getLeftChild(); const node1RightChild = node1.getRightChild(); const node2Parent = node2.getParent(); const node2LeftChild = node2.getLeftChild(); const node2RightChild = node2.getRightChild(); const node1Color = node1.getColor(); const node2Color = node2.getColor(); node1.setLeftChild(node2LeftChild); node1.setRightChild(node2RightChild); node2.setLeftChild(node1LeftChild); node2.setRightChild(node1RightChild); node1.setColor(node2Color); node2.setColor(node1Color); if(node1Parent == null) { this.tree.setRoot(node2); } else { node1Parent.substituteNode(node1, node2); } if(node2Parent == null) { this.tree.setRoot(node1); } else { node2Parent.substituteNode(node2, node1); } } } swapChildParent(parent: TreeNode<T>, child: TreeNode<T>): void { const parentColor = parent.getColor(); const childColor = child.getColor(); const leftGrandChild = child.getLeftChild(); const rightGrandChild = child.getRightChild(); const grandParent = parent.getParent(); if(grandParent == null) { this.tree.setRoot(child); } else if(grandParent.isLeftChild(parent)) { grandParent.setLeftChild(child); } else { grandParent.setRightChild(child); } if(parent.isLeftChild(child)) { const rightChild = parent.getRightChild(); child.setLeftChild(parent); child.setRightChild(rightChild); } else { const leftChild = parent.getLeftChild(); child.setRightChild(parent); child.setLeftChild(leftChild); } child.setColor(parentColor); parent.setLeftChild(leftGrandChild); parent.setRightChild(rightGrandChild); parent.setColor(childColor); } }