Tims-Chat/files_wcf/js/Bastelstu.be/Chat/DataStructure/RedBlackTree/Node.js

150 lines
3.5 KiB
JavaScript

/*
* Copyright (c) 2010-2018 Tim Düsterhus.
*
* Use of this software is governed by the Business Source License
* included in the LICENSE file.
*
* Change Date: 2024-11-01
*
* On the date above, in accordance with the Business Source
* License, use of this software will be governed by version 2
* or later of the General Public License.
*/
define([], function () {
'use strict'
class Node {
constructor(value) {
this.value = value
this._left = undefined
this._right = undefined
this.parent = undefined
this.color = 'RED'
}
get left() {
return this._left
}
set left(node) {
if (this._left) this._left.parent = undefined
if (node !== undefined) {
if (node.parent !== undefined) {
if (node.isLeftChild) node.parent.left = undefined
else if (node.isRightChild) node.parent.right = undefined
else throw new Error('Unreachable')
}
node.parent = this
}
this._left = node
}
get right() {
return this._right
}
set right(node) {
if (this._right) this._right.parent = undefined
if (node !== undefined) {
if (node.parent !== undefined) {
if (node.isLeftChild) node.parent.left = undefined
else if (node.isRightChild) node.parent.right = undefined
else throw new Error('Unreachable')
}
node.parent = this
}
this._right = node
}
get isRoot() {
return this.parent === undefined
}
get isLeaf() {
return this.left === undefined && this.right === undefined
}
get isLeftChild() {
if (this.parent === undefined) return false
return this.parent.left === this
}
get isRightChild() {
if (this.parent === undefined) return false
return this.parent.right === this
}
get grandparent() {
if (this.parent === undefined) return undefined
return this.parent.parent
}
get sibling() {
if (this.parent === undefined) return undefined
if (this.isLeftChild) return this.parent.right
return this.parent.left
}
get uncle() {
if (this.parent === undefined) return undefined
return this.parent.sibling
}
search(value) {
if (value === this.value) return ['IS', this]
if (value < this.value) {
if (this.left !== undefined) return this.left.search(value)
return ['LEFT', this]
}
if (value > this.value) {
if (this.right !== undefined) return this.right.search(value)
return ['RIGHT', this]
}
throw new Error('Unreachable')
}
print(depth = 0) {
console.log(
' '.repeat(depth) +
`${this.value}: ${this.color} (Parent: ${
this.parent ? this.parent.value : '-'
})`
)
if (this.left) this.left.print(depth + 1)
else console.log(' '.repeat(depth + 1) + '-')
if (this.right) this.right.print(depth + 1)
else console.log(' '.repeat(depth + 1) + '-')
}
check() {
if (this.left && this.left.value >= this.value)
throw new Error('Invalid' + this.value)
if (this.right && this.right.value <= this.value)
throw new Error('Invalid' + this.value)
if (
this.color === 'RED' &&
((this.left && this.left.color !== 'BLACK') ||
(this.right && this.right.color !== 'BLACK'))
)
throw new Error('Invalid' + this.value)
let leftBlacks = 1,
rightBlacks = 1
if (this.left) {
leftBlacks = this.left.check()
}
if (this.right) {
rightBlacks = this.right.check()
}
if (leftBlacks !== rightBlacks) throw new Error('Invalid' + this.value)
if (this.color === 'BLACK') return leftBlacks + 1
return leftBlacks
}
}
return Node
})