92 lines
2.2 KiB
JavaScript
92 lines
2.2 KiB
JavaScript
function tree(less, val, more) {
|
|
return {
|
|
depth: 1+Math.max(less.depth, more.depth),
|
|
less: less,
|
|
val: val,
|
|
more: more,
|
|
};
|
|
}
|
|
|
|
function node(val) {
|
|
return tree({depth: 0}, val, {depth: 0});
|
|
}
|
|
|
|
function insert(x,y) {
|
|
if (0 == y.depth) return x;
|
|
if (0 == x.depth) return y;
|
|
if (1 == x.depth && 1 == y.depth) {
|
|
switch (Math.sign(y.val)-x.val) {
|
|
case -1: return tree(y, x.val, {depth: 0});
|
|
case 0: return y;
|
|
case 1: return tree(x, y.val, {depth: 0});
|
|
}
|
|
}
|
|
switch (Math.sign(y.val-x.val)) {
|
|
case -1: return balance(insert(x.less, y), x.val, x.more);
|
|
case 0: return balance(insert(x.less, y.less), x.val, insert(x.more, y.more));
|
|
case 1: return balance(x.less. x.val, insert(x.more, y));
|
|
}
|
|
}
|
|
|
|
function balance(less,val,more) {
|
|
if (2 > Math.abs(less.depth-more.depth))
|
|
return tree(less,val,more);
|
|
if (more.depth > less.depth) {
|
|
if (more.more.depth >= more.less.depth) {
|
|
// 'more' was heavy
|
|
return moreHeavy(less, val, more);
|
|
} else {
|
|
return moreHeavy(less,val,lessHeavy(more.less, more.val, more.more));
|
|
}
|
|
} else {
|
|
if(less.less.depth >= less.more.depth) {
|
|
return lessHeavy(less, val, more);
|
|
} else {
|
|
return lessHeavy(moreHeavy(less.less, less.val, less.more), val, more);
|
|
}
|
|
}
|
|
}
|
|
|
|
function moreHeavy(less,val,more) {
|
|
return tree(tree(less,val,more.less), more.val, more.more)
|
|
}
|
|
|
|
function lessHeavy(less,val,more) {
|
|
return tree(less.less, less.val, tree(less.more, val, more));
|
|
}
|
|
|
|
function remove(val, y) {
|
|
switch (y.depth) {
|
|
case 0: return y;
|
|
case 1:
|
|
if (val == y.val) {
|
|
return y.less;
|
|
} else {
|
|
return y;
|
|
}
|
|
default:
|
|
switch (Math.sign(y.val - val)) {
|
|
case -1: return balance(y.less, y.val, remove(val, y.more));
|
|
case 0: return insert(y.less, y.more);
|
|
case 1: return balance(remove(val, y.less), y.val, y.more)
|
|
}
|
|
}
|
|
}
|
|
|
|
function lookup(val, y) {
|
|
switch (y.depth) {
|
|
case 0: return y;
|
|
case 1: if (val == y.val) {
|
|
return y;
|
|
} else {
|
|
return {depth: 0};
|
|
}
|
|
default:
|
|
switch (Math.sign(y.val-val)) {
|
|
case -1: return lookup(val, y.more);
|
|
case 0: return y;
|
|
case 1: return lookup(val, y.less);
|
|
}
|
|
}
|
|
}
|