Я уже несколько дней ломаю голову над этой проблемой, пробуя всевозможные реализации дерева AVL в JavaScript. Это самое близкое, что я получил до сих пор, но вращение работает не так, как ожидалось, и мне постоянно приходится переустанавливать this.root
каждый раз, когда я вставляю новое значение. Я хочу, чтобы моя реализация могла добавлять несколько значений, поэтому я разрешаю передавать массив или одно значение (поэтому я использую очередь).
Результат теста для: bst.insert([50, 40, 30, 32, 34, 38, 39, 38.5, 55, 27]
возвращается очень неправильно. Фактические значения после заказа должны возвращаться как: [27, 32, 30, 38.5, 39, 38, 50, 55, 40, 34]
, но возвращается [27, 30, 32, 38, 39, 55, 50, 40, 38.5, 34]
.
Я полагаю, что проблема возникает где-то в методе insertHelper
во время рекурсии, но я не могу определить ее сам в этой точке и был бы очень признателен за sh и не злой пара глаз, чтобы проверить мой код. По сути, не все узлы повторно балансируют и рекурсивно вращаются обратно к узлу root, и я не уверен, почему моя рекурсия не может этого сделать.
getBF(node) {
if (node === null) {
return 0;
}
return this.getHeight(node.left) - this.getHeight(node.right);
}
getHeight(node) {
if (node === null) {
return -1;
}
return node.height;
}
insert(value) {
let queue = new Plus.Queue();
if (value === undefined) {
return;
} else if (Array.isArray(value)) {
value.forEach((val) => queue.enqueue(val));
} else {
queue.enqueue(value);
}
let currentValue;
let newNode;
while (queue.data.length > 0) {
currentValue = queue.dequeue();
if (this.validData(currentValue)) {
newNode = new Plus.TreeNode(currentValue);
if (this.root === null) {
this.root = newNode;
} else {
this.root = this.insertHelper(this.root, newNode);
}
} else {
if (!this.duplicates[currentValue]) {
this.duplicates[currentValue] = 0;
}
this.duplicates[currentValue] += 1;
}
}
return this;
}
insertHelper(root, node) {
if (root === null) {
root = node;
} else if (this.compareFunction(node.val, root.val)) {
root.left = this.insertHelper(root.left, node);
} else {
root.right = this.insertHelper(root.right, node);
}
root = this.update(root);
return this.balance(root);
}
update(node) {
let lh, rh;
[lh, rh] = [-1, -1];
if (node.left) {
lh = node.left.height;
}
if (node.right) {
rh = node.right.height;
}
node.height = 1 + Math.max(lh, rh);
node.bf = rh - lh;
return node;
}
balance(node) {
if (node.bf > 1) {
if (node.right.bf >= 0) {
node = this.rotationRightRight(node);
} else {
node = this.rotationRightLeft(node);
}
} else if (node.bf < -1) {
if (node.left.bf <= 0) {
node = this.rotationLeftLeft(node);
} else {
node = this.rotationLeftRight(node);
}
}
return node;
}
rotationLeftLeft(node) {
let newHead = node.left;
let t3 = newHead.right;
newHead.right = node;
node.left = t3;
newHead = this.update(newHead);
node = this.update(node);
return newHead;
}
rotationLeftRight(node) {
node.left = this.rotationRightRight(node.left);
return this.rotationLeftLeft(node);
}
rotationRightRight(node) {
let newHead = node.right;
node.right = newHead.left;
newHead.left = node;
newHead = this.update(newHead);
node = this.update(node);
return newHead;
}
rotationRightLeft(node) {
node.right = this.rotationLeftLeft(node.right);
return this.rotationRightRight(node);
}
The BST
- это функция class
, которую я использую для этого. Все эти методы являются методами функции конструктора BST
. Я почти уверен, что ошибка не возникает с этим, поэтому я пропустил эту часть кода, но если вы думаете, что это поможет, я тоже загрузлю это.
Вот Node
класс, с которым я работаю для отдельных узлов в дереве AVL.
Plus.TreeNode = class {
constructor(val = null, left, right) {
this.val = val;
this.left = null;
this.right = null;
this.height = 0;
this.bf = 0;
}
};
И вот возвращаемое значение метода insert
, описанного выше:
{ val: 34,
left:
{ val: 32,
left: { val: 30, left: [Object], right: null, height: 1, bf: -1 },
right: null,
height: 2,
bf: -2 },
right:
{ val: 38.5,
left: { val: 38, left: null, right: null, height: 0, bf: 0 },
right: { val: 40, left: [Object], right: [Object], height: 2, bf: 1 },
height: 3,
bf: 2 },
height: 7,
bf: 4 }
Спасибо заранее!