2017-07-16 18:26:17 +02:00
|
|
|
fn defaultCompare(a, b) {
|
|
|
|
switch {
|
|
|
|
case a < b: -1
|
|
|
|
case a > b: 1
|
|
|
|
default: 0
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-07-16 23:15:42 +02:00
|
|
|
let empty {}
|
2017-07-16 18:26:17 +02:00
|
|
|
|
|
|
|
fn treeWithCompare(compare) {
|
|
|
|
compare: compare
|
2017-07-16 23:15:42 +02:00
|
|
|
node: empty
|
2017-07-16 18:26:17 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
let tree treeWithCompare(defaultCompare)
|
|
|
|
|
2017-07-16 23:15:42 +02:00
|
|
|
let hasLess hasField("less")
|
|
|
|
let hasGreater hasField("greater")
|
|
|
|
|
2017-07-16 18:26:17 +02:00
|
|
|
fn nextNode(compare, node, value) {
|
2017-07-16 23:15:42 +02:00
|
|
|
let greater node != empty && compare(node.value, value) > 0
|
|
|
|
switch {
|
|
|
|
case greater && hasLess(node):
|
|
|
|
nextNode(compare, node.less, value)
|
|
|
|
case greater:
|
|
|
|
node
|
|
|
|
case hasGreater(node):
|
|
|
|
nextNode(compare, node.greater, value)
|
|
|
|
default:
|
|
|
|
empty
|
2017-07-16 18:26:17 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
fn prevNode(compare, node, value) {
|
2017-07-16 23:15:42 +02:00
|
|
|
let less node != empty && compare(node.value, value) < 0
|
|
|
|
switch {
|
|
|
|
case less && hasGreater(node):
|
|
|
|
prevNode(compare, node.greater, value)
|
|
|
|
case less:
|
|
|
|
node
|
|
|
|
case hasLess(node):
|
|
|
|
prevNode(compare, node.less, value)
|
|
|
|
default:
|
|
|
|
empty
|
2017-07-16 18:26:17 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
fn findNode(compare, node, value) {
|
|
|
|
switch {
|
2017-07-17 04:23:29 +02:00
|
|
|
case node == empty: false
|
2017-07-16 18:26:17 +02:00
|
|
|
case node.value == value: true
|
|
|
|
case compare(node.value, value) < 0:
|
|
|
|
findNode(compare, node.greater, value)
|
|
|
|
default:
|
|
|
|
findNode(compare, node.less, value)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
fn delNode(compare, node, value) {
|
|
|
|
fn delBetween() {
|
|
|
|
let next nextNode(compare, node, node.value)
|
2017-07-29 23:40:45 +02:00
|
|
|
{
|
|
|
|
node...
|
|
|
|
value: next.value
|
|
|
|
greater: delNode(compare, node.greater, next.value)
|
2017-07-16 18:26:17 +02:00
|
|
|
} /* -> updateDepth() */ -> balance()
|
|
|
|
}
|
|
|
|
|
|
|
|
fn delCurrent() {
|
|
|
|
match node {
|
|
|
|
case {less, greater}: delBetween()
|
2017-07-17 04:23:29 +02:00
|
|
|
case {less}: node.less
|
|
|
|
case {greater}: node.greater
|
2017-07-16 18:26:17 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
fn delGreater() {
|
|
|
|
match node {
|
|
|
|
case {greater}:
|
2017-07-29 23:40:45 +02:00
|
|
|
{
|
|
|
|
node...
|
|
|
|
greater: delNode(compare, node.greater, node.value)
|
2017-07-16 23:15:42 +02:00
|
|
|
} -> balance()
|
2017-07-16 18:26:17 +02:00
|
|
|
default:
|
|
|
|
node
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
fn delLess() {
|
|
|
|
match node {
|
|
|
|
case {less}:
|
2017-07-29 23:40:45 +02:00
|
|
|
{
|
|
|
|
node...
|
|
|
|
less: delNode(compare, node.less, node.value)
|
2017-07-16 23:15:42 +02:00
|
|
|
} -> balance()
|
2017-07-16 18:26:17 +02:00
|
|
|
default:
|
|
|
|
node
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
fn delNode() {
|
|
|
|
let c compare(node.value, value)
|
|
|
|
switch {
|
|
|
|
case c == 0: delCurrent()
|
|
|
|
case c < 0: delGreater()
|
|
|
|
default: delLess()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-07-16 23:15:42 +02:00
|
|
|
node == empty ? empty : delNode()
|
2017-07-16 18:26:17 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
fn insertNode(compare, node, value) {
|
2017-07-16 23:15:42 +02:00
|
|
|
let (
|
|
|
|
empty node == empty
|
|
|
|
c empty ? 0 : compare(node.value, value)
|
|
|
|
insertGreater fn() {
|
|
|
|
node...
|
|
|
|
greater: insertNode(
|
|
|
|
compare
|
|
|
|
node.greater
|
|
|
|
value
|
|
|
|
)
|
|
|
|
}
|
|
|
|
insertLess fn() {
|
|
|
|
node...
|
|
|
|
less: insertNode(
|
|
|
|
compare
|
|
|
|
node.less
|
|
|
|
value
|
|
|
|
)
|
2017-07-16 18:26:17 +02:00
|
|
|
}
|
2017-07-16 23:15:42 +02:00
|
|
|
)
|
|
|
|
|
|
|
|
switch {
|
|
|
|
case empty: {value: value}
|
|
|
|
case c > 0: insertGreater() -> balance()
|
|
|
|
case c < 0: insertLess() -> balance()
|
2017-07-17 04:23:29 +02:00
|
|
|
default: node
|
2017-07-16 18:26:17 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
fn prevNextValue(f, tree, value) {
|
|
|
|
let node f(tree.compare, tree.node, value)
|
2017-07-16 23:15:42 +02:00
|
|
|
node == empty ? value : node.value
|
2017-07-16 18:26:17 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
fn update(f, tree, value) {
|
|
|
|
tree...
|
|
|
|
node: f(tree.compare, tree.node, value)
|
|
|
|
}
|
|
|
|
|
2017-07-16 23:15:42 +02:00
|
|
|
type alias tree {compare: fn(a, a) int, node: {}}
|
|
|
|
type next fn(tree, a) a
|
|
|
|
type prev fn(tree, a) a
|
|
|
|
type find fn(tree, a) bool
|
|
|
|
type delete fn(tree, a) tree
|
|
|
|
type insert fn(tree, a) tree
|
2017-07-16 18:26:17 +02:00
|
|
|
|
|
|
|
let (
|
|
|
|
next = prevNextValue(prevNode)
|
|
|
|
prev = prevNextValue(nextNode)
|
|
|
|
)
|
|
|
|
|
2017-07-16 23:15:42 +02:00
|
|
|
fn find(tree, value) findNode(tree.compare, tree.node, value) != empty
|
2017-07-16 18:26:17 +02:00
|
|
|
|
|
|
|
let (
|
|
|
|
del update(delNode)
|
|
|
|
insert update(insertNode)
|
|
|
|
)
|