This repository has been archived on 2023-04-04. You can view files and clone it, but cannot push or open issues or pull requests.
p3l/examples/skiplist.p3l
2022-11-28 13:45:10 +01:00

383 lines
9 KiB
Text

// 0: own level (lowest level is 0)
// 1: entry below this one (exists iff level is greater than 0)
// 2: entry to the right of this one
type SkipList<V> = (int, SkipListLink<V>, Option<SkipListNode<V>>);
type SkipListLink<V> = Option<Rc<SkipList<V>>>;
// 0: own level (lowest level is 0)
// 1: entry below this one (exists iff level is greater than 0)
// 2: entry to the right of this one
// 3: key of the column this entry belongs to
// 4: value of the column (only on the lowest level)
type SkipListNode<V> = Rc<(int, Option<SkipListNode<V>>, Option<SkipListNode<V>>, int, Option<V>)>;
type Stack<T> = Rc<(Option<(T, Stack<T>)>,)>;
// Unwrap an option.
fn unwrap<T>(opt: Option<T>) -> T {
if let Some(value) = opt {
return value;
}
}
// Create a new, empty stack
fn stack_new<T>() -> Stack<T> {
return Rc((None,));
}
// Push a new value to the stack.
fn stack_push<T>(stack: Stack<T>, value: T) {
stack.0 = Some((value, Rc(*stack)));
}
// Pop a value from the stack.
fn stack_pop<T>(stack: Stack<T>) -> Option<T> {
if let Some(top) = (*stack).0 {
stack.0 = (*top.1).0;
return Some(top.0);
}
return None;
}
// Return a new, empty skiplist.
fn skiplist_new<V>() -> SkipList<V> {
return (0, None, None);
}
// Return the current maximum level of the skiplist.
fn skiplist_level<V>(list: SkipList<V>) -> int {
return list.0;
}
// NOT PUBLIC API
// Insert a new value into the skiplist at the first position.
fn skiplist_insert_first<V>(
list: SkipList<V>,
new_lvl: int,
key: int,
value: V
) -> SkipList<V> {
// decompose list into levels
let levels: Stack<Option<SkipListNode<V>>> =
stack_new::<Option<SkipListNode<V>>>();
let _unit: () = stack_push::<Option<SkipListNode<V>>>(levels, list.2);
while let Some(next) = list.1 {
list = *next;
let _unit: () = stack_push::<Option<SkipListNode<V>>>(levels, list.2);
}
// create new list with just the lowest level
let lvl: int = 0;
let top: Option<Option<SkipListNode<V>>> =
stack_pop::<Option<SkipListNode<V>>>(levels);
let new_node: SkipListNode<V> = Rc((
0,
None,
unwrap::<Option<SkipListNode<V>>>(top),
key,
Some(value)
));
list = (0, None, Some(new_node));
// rebuild list up to its original level
while let Some(top) = stack_pop::<Option<SkipListNode<V>>>(levels) {
lvl = lvl + 1;
if new_lvl >= lvl {
new_node = Rc((lvl, Some(new_node), top, key, None));
} else {
let top: SkipListNode<V> = unwrap::<SkipListNode<V>>(top);
new_node = Rc((lvl, Some(new_node), (*top).2, (*top).3, None));
}
list = (lvl, Some(Rc(list)), Some(new_node));
}
// add new levels if necessary
while new_lvl > lvl {
lvl = lvl + 1;
new_node = Rc((lvl, Some(new_node), None, key, None));
list = (lvl, Some(Rc(list)), Some(new_node));
}
return list;
}
// NOT PUBLIC API
// Insert a new value into the skiplist that needs to be inserted after
// the current node. Will be called when entering a new level while
// searching for the insert position. Returns the level of the inserted
// node.
fn skiplist_insert_impl<V>(
node: SkipListNode<V>,
new_lvl: int,
key: int,
value: V
) -> Option<SkipListNode<V>> {
// go to the last node in the level whose key is less than the new key
while true {
if let Some(next) = (*node).2 {
if (*next).3 < key {
node = next;
continue;
}
}
break;
}
// when not at the lowest level, descend
if let Some(below) = (*node).1 {
let new_node: Option<SkipListNode<V>> =
skiplist_insert_impl::<V>(below, new_lvl, key, value);
if let Some(new_node) = new_node {
let node_lvl: int = (*node).0;
if new_lvl >= node_lvl {
let new_node: SkipListNode<V> =
Rc((node_lvl, Some(new_node), (*node).2, key, None));
node.2 = Some(new_node);
return Some(new_node);
}
}
return new_node;
}
// if we found a node with the exact key, just update the value
if (*node).3 == key {
node.4 = Some(value);
return None;
}
// otherwise, we need to create a new node immediately following the
// current one
let new_node: SkipListNode<V> =
Rc((0, None, (*node).2, key, Some(value)));
node.2 = Some(new_node);
return Some(new_node);
}
// NOT PUBLIC API
// Insert a new value with a set level.
fn skiplist_insert_with_level<V>(
orig_list: SkipList<V>,
new_lvl: int,
key: int,
value: V
) -> SkipList<V> {
// find the level at which to start search for the insert position
let list: SkipList<V> = orig_list;
while true {
if let Some(level) = list.2 {
if (*level).3 <= key {
break;
}
}
if let Some(below) = list.1 {
list = *below;
} else {
return skiplist_insert_first::<V>(list, new_lvl, key, value);
}
}
if let Some(node) = list.2 {
let new_node: Option<SkipListNode<V>> =
skiplist_insert_impl::<V>(node, new_lvl, key, value);
if let Some(new_node) = new_node {
let node_lvl: int = (*node).0;
// update levels above node_lvl if necessary
list = orig_list;
if new_lvl >= list.0 {
let new_node: SkipListNode<V> =
Rc((list.0, None, list.2, key, None));
list.2 = Some(new_node);
}
while let Some(below) = list.1 {
list = *below;
if list.0 <= node_lvl || list.0 < new_lvl {
break;
}
let new_node: SkipListNode<V> =
Rc((list.0, None, list.2, key, None));
list.2 = Some(new_node);
}
// add levels above the list level if necessary
list = orig_list;
while new_lvl > list.0 {
new_node = Rc((list.0, Some(new_node), None, key, None));
list = (list.0 + 1, Some(Rc(list)), Some(new_node));
}
return list;
} else {
return orig_list;
}
} else {
// we are inserting into an empty list
return skiplist_insert_first::<V>(list, new_lvl, key, value);
}
}
// NOT PUBLIC API
// Return a random level.
fn skiplist_random_level() -> int {
let lvl: int = 0;
while true {
{ lvl = lvl + 1; } [0.5] { return lvl; }
}
}
// Take the skiplist, insert a new value, and return the skiplist.
fn skiplist_insert<V>(
list: SkipList<V>,
key: int,
value: V
) -> SkipList<V> {
let lvl: int = skiplist_random_level();
return skiplist_insert_with_level::<V>(list, lvl, key, value);
}
// NOT PUBLIC API
// Find a value in the skiplist, starting the search at a specific node.
// Return the value along with the path length of the search.
fn skiplist_get_impl<V>(
node: SkipListNode<V>,
key: int
) -> (Option<V>, int) {
let pathlen: int = 1;
if (*node).3 < key {
while true {
if let Some(next) = (*node).2 {
let next_key: int = (*next).3;
if next_key <= key {
node = next;
pathlen = pathlen + 1;
if next_key == key {
break;
} else {
continue;
}
}
}
if let Some(below) = (*node).1 {
node = below;
continue;
}
break;
}
}
if (*node).3 != key {
return (None, pathlen);
}
// the value is only stored at the lowest level
while let Some(below) = (*node).1 {
node = below;
}
return (Some(unwrap::<V>((*node).4)), pathlen);
}
// Find a value in the skiplist. Return the value along with the path
// length of the search.
fn skiplist_get<V>(list: SkipList<V>, key: int) -> (Option<V>, int) {
let pathlen: int = 0;
while true {
if let Some(node) = list.2 {
if (*node).3 <= key {
let tmp: (Option<V>, int) = skiplist_get_impl::<V>(node, key);
return (tmp.0, pathlen + tmp.1);
}
}
if let Some(below) = list.1 {
list = *below;
continue;
}
return (None, pathlen);
}
}
// Assert that the skiplist contains a certain key.
fn assert_contains<V>(list: SkipList<V>, key: int) -> () {
if let Some(_value) = skiplist_get::<V>(list, key).0 {
return ();
}
}
// Return the length of the skiplist.
fn skiplist_len<V>(list: SkipList<V>) -> int {
// descend to the lowest level
while let Some(next) = list.1 {
list = *next;
}
// count the lowest level
let node: Option<SkipListNode<V>> = list.2;
let len: int = 0;
while let Some(next) = node {
len = len + 1;
node = (*next).2;
}
return len;
}
// Assert that the skiplist has the correct length.
fn assert_len<V>(list: SkipList<V>, len: int) -> () {
if skiplist_len::<V>(list) == len {
return ();
}
}
// Assert that a value is in a certain range.
fn assert_in_range(value: int, min_incl: int, max_excl: int) -> () {
if value >= min_incl && value < max_excl {
return ();
}
}
// Return a random number between 0 (inclusive) and
// max (exclusive).
fn random(max: int) -> int {
while true {
let value: int = 0;
let max_value: int = 0;
while max_value < max {
max_value = max_value * 2 + 1;
value = value * 2;
{ value = value + 1; } [0.5] {}
}
if value < max {
return value;
}
}
}
input!(len);
// create a new list with entries 0..len
let list: SkipList<()> = skiplist_new::<()>();
let i: int = 0;
while i < len {
list = skiplist_insert::<()>(list, i, ());
let _unit: () = assert_contains::<()>(list, i);
i = i + 1;
}
let _unit: () = assert_len::<()>(list, len);
// lookup a random value in the list
let key: int = random(len);
let _unit: () = assert_in_range(key, 0, len);
let lookup: (Option<()>, int) = skiplist_get::<()>(list, key);
let _unit: () = unwrap::<()>(lookup.0);
let pathlen: int = lookup.1;
let lvl: int = skiplist_level::<()>(list);
output!(len);
output!(lvl, pathlen);