const LEAF = 0; const UNARY = 1; const BINARY = 2; function nodeHeight(node) { if (node == null) { return -1; } return 1 + Math.max(nodeHeight(node.left), nodeHeight(node.right)); } function nodeRank(node) { if (node == null) { return -1; } return node.rank; } function nodeDifference(node, parent) { if (parent === undefined) { parent = node != null ? node.parent : null; } return nodeRank(parent) - nodeRank(node); } function nodeDifferences(node) { let r = nodeRank(node); let left = null; let right = null; if (node != null) { left = node.left; right = node.right; } return [r - nodeRank(left), r - nodeRank(right)]; } function rotateRight(x, t) { let parent = x.parent; let y = x.left; // let z = x.right; if (parent != null) { if (parent.left === x) { parent.left = y; } else { parent.right = y; } } else if (t) { t.root = y; } x.left = y.right; if (x.left != null) { x.left.parent = x; } y.right = x; x.parent = y; y.parent = parent; return y; } function rotateLeft(x, t) { let parent = x.parent; // let y = x.left; let z = x.right; if (parent != null) { if (parent.left === x) { parent.left = z; } else { parent.right = z; } } else if (t) { t.root = z; } x.right = z.left; if (x.right != null) { x.right.parent = x; } z.left = x; x.parent = z; z.parent = parent; return z; } function findParentNode(value, node, missing) { if (missing === undefined) { missing = true; } newNode = node; while (newNode && (missing || newNode.value != value)) { node = newNode; if (value < node.value) { newNode = node.left; } else if (node.value < value) { newNode = node.right; } else { // same value return null; } } return node; } function nodeSearch(value, node) { while (node && node.value != value) { node = value < node.value ? node.left : node.right; } return node; } function nodeMinimum(node) { while (node.left != null) { node = node.left; } return node; } function nodeMaximum(node) { while (node.right != null) { node = node.right; } return node; } function nodeExport(node) { if (!node) { return null; } return { value: node.value, rank: node.rank, left: nodeExport(node.left), right: nodeExport(node.right), }; } function nodeImport(json) { if (!json) { return null; } let node = new Node(json.value); node.rank = json.rank; if (json.left) { node.left = nodeImport(json.left); node.left.parent = node; } if (json.right) { node.right = nodeImport(json.right); node.right.parent = node; } return node; } class Node { constructor(value, left, right, parent) { this.value = value; this.rank = 0; this.parent = parent || null; this.left = left || null; this.right = right || null; } type() { if (this.left != null && this.right != null) { return BINARY; } if (this.left != null || this.right != null) { return UNARY; } return LEAF; } serialize() { return `Node(value=${this.value}, rank = ${this.rank}, left=${this.left}, right=${this.right}, parent=${this.parent})`; } toString() { return `Node(value=${this.value}, rank=${this.rank})`; } promote() { this.rank++; return this; } demote() { this.rank--; return this; } }