2022-04-27 21:37:58 +02:00
|
|
|
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)];
|
|
|
|
}
|
|
|
|
|
2022-05-22 20:27:02 +02:00
|
|
|
function rotateRight(t, x) {
|
2022-04-27 21:37:58 +02:00
|
|
|
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;
|
|
|
|
}
|
2022-05-20 15:29:50 +02:00
|
|
|
} else if (t) {
|
|
|
|
t.root = y;
|
2022-04-27 21:37:58 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
x.left = y.right;
|
|
|
|
if (x.left != null) {
|
|
|
|
x.left.parent = x;
|
|
|
|
}
|
|
|
|
|
|
|
|
y.right = x;
|
|
|
|
x.parent = y;
|
|
|
|
y.parent = parent;
|
|
|
|
|
|
|
|
return y;
|
|
|
|
}
|
|
|
|
|
2022-05-22 20:27:02 +02:00
|
|
|
function rotateLeft(t, x) {
|
2022-04-27 21:37:58 +02:00
|
|
|
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;
|
|
|
|
}
|
2022-05-20 15:29:50 +02:00
|
|
|
} else if (t) {
|
|
|
|
t.root = z;
|
2022-04-27 21:37:58 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2022-05-01 17:09:46 +02:00
|
|
|
newNode = node;
|
2022-04-27 21:37:58 +02:00
|
|
|
|
|
|
|
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) {
|
2022-05-01 17:09:46 +02:00
|
|
|
node = value < node.value ? node.left : node.right;
|
2022-04-27 21:37:58 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2022-05-15 18:15:37 +02:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2022-04-27 21:37:58 +02:00
|
|
|
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;
|
|
|
|
}
|
2022-05-01 17:09:46 +02:00
|
|
|
}
|