Skip to content

Commit

Permalink
Tweak docs again..
Browse files Browse the repository at this point in the history
  • Loading branch information
nielsenko committed Dec 8, 2023
1 parent bd879ff commit a17778b
Show file tree
Hide file tree
Showing 2 changed files with 53 additions and 39 deletions.
8 changes: 6 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
A library implementing a persistent treap data structure for Dart developers.
A package implementing a persistent treap data structure.

## Usage

Expand Down Expand Up @@ -27,7 +27,11 @@ main() {
}
```

For something more significant see the [todo](example/) flutter app
For something more substantial see the [todo](example/) flutter app.

It illustrates how to use a persistent treap to handle undo/redo and animate a list view.

If your browser supports WasmGC (such as Chrome 119+, or Firefox 120+), you can try out the app [here](https://byolimit.github.io)

## Status

Expand Down
84 changes: 47 additions & 37 deletions lib/src/treap_base.dart
Original file line number Diff line number Diff line change
Expand Up @@ -4,32 +4,46 @@ import 'node.dart';

final _rnd = Random(42);

/// Treap class
/// A treap is a type of binary search tree data structure that maintains a dynamic
/// set of ordered keys and allows binary search tree operations in addition to operations
/// like add, find, and erase in O(log n) time. The name 'Treap' is a portmanteau
/// of tree and heap, as the tree maintains its shape using heap properties.
/// A persistent treap class
///
/// The name [Treap] is a portmanteau of tree and heap.
///
/// A treap is a type of binary search tree. Each node in the tree is assigned a
/// uniformly distributed priority, either randomly or by a strong hash.
///
/// Nodes in the tree are rotated to ensure they are heap-ordered wrt. their priority.
/// This ensures that the shape of the tree is a random variable with the same probability
/// distribution as a random binary tree.
///
/// In particular (with high probability), given a treap with `N` keys, the height
/// is `O(log(N))`, so that each search, insertion, or deletion operation
/// also takes `O(log(N))` time to perform. In other words; with high probability
/// a treap forms a balanced binary tree.
///
/// This particular treap implementation is fully persistent (immutable), by means
/// of path copying. https://en.wikipedia.org/wiki/Persistent_data_structure.
class Treap<T extends Comparable<T>> {
final Node<T>? _root;

const Treap._(this._root);

/// Create an empty treap
const Treap() : this._(null);

/// The build method takes an iterable of items and constructs a treap from them.
/// It does this by folding over the items, adding each one to the treap in turn.
/// This method is O(N log(N)) in complexity. An O(N) algorithm exists if the items
/// The build factory takes an iterable of [items] and constructs a treap from them.
/// It does this by folding [add] over the items, adding each one to the treap in turn.
/// This method is `O(N log(N))` in complexity. An `O(N)` algorithm exists if the items
/// are sorted. However, this method is simpler and works even if the items are not
/// sorted.
factory Treap.build(Iterable<T> items) =>
items.fold(Treap(), (acc, i) => acc.add(i));

/// Adds an item to the treap. Creates a new node with the item and a random priority.
/// The new node is then added to the root of the treap. Returns a new treap with the
/// added node.
/// Adds an [item] to the treap. Creates a new node with the [item] and a random priority.
/// Returns a new treap with the added node.
Treap<T> add(T item) =>
Treap<T>._(_root.add(Node<T>(item, _rnd.nextInt(1 << 32))));

/// Erases an item from the treap. Returns a new treap without the erased item.
/// Erases an [item] from the treap. Returns a new treap without the erased [item].
Treap<T> erase(T item) => Treap._(_root.erase(item));

/// Checks if the treap is empty. Returns true if the treap is empty, false otherwise.
Expand All @@ -38,26 +52,26 @@ class Treap<T extends Comparable<T>> {
/// Returns the size of the treap.
int get size => _root.size;

/// Finds an item in the treap. Returns the item if found, null otherwise.
/// Finds an [item] in the treap. Returns the item if found, `null` otherwise.
T? find(T item) => _root.find(item)?.item;

/// Checks if an item exists in the treap. Returns true if the item exists, false
/// otherwise.
/// Checks if an [item] exists in the treap. Returns `true` if the item exists,
/// `false` otherwise.
bool has(T item) => find(item) != null;

/// Returns the rank of an item in the treap.
/// Returns the rank of an [item] in the treap.
int rank(T item) => _root.rank(item);

/// Selects an item in the treap by its rank. Returns the selected item.
/// Selects an item in the treap by its [rank]. Returns the selected item.
T select(int rank) => _root.select(rank).item;

/// Returns all the values in the treap.
Iterable<T> get values => _root.values;

/// Returns the first item in the treap, or null if the treap is empty.
/// Returns the first item in the treap, or `null` if the treap is empty.
T? get firstOrDefault => _root?.min;

/// Returns the last item in the treap, or null if the treap is empty.
/// Returns the last item in the treap, or `null` if the treap is empty.
T? get lastOrDefault => _root?.max;

/// Returns the first item in the treap. Throws an error if the treap is empty.
Expand All @@ -72,46 +86,42 @@ class Treap<T extends Comparable<T>> {
/// Returns the next item in the treap for a given item.
T next(T item) => _root.select(rank(item) + 1).item;

/// Returns a new treap with the first n items. If n is greater than the size of
/// the treap, returns the original treap.
/// Returns a new treap with the first [n] items. If [n] is greater than the [size]
/// of the treap, returns the original treap.
Treap<T> take(int n) =>
n < size ? Treap._(_root.split(_root.select(n).item).low) : this;

/// Skips the first n items and returns a new treap with the remaining items.
/// If n is greater than or equal to the size of the treap, returns an empty treap.
/// Skips the first [n] items and returns a new treap with the remaining items.
/// If [n] is greater than or equal to the [size] of the treap, returns an empty
/// treap.
Treap<T> skip(int n) {
if (n >= size) return Treap(); // empty
final split = _root.split(_root.select(n).item);
return Treap._(split.high.union(split.middle));
}

/// Returns a new treap that is the union of this treap and another treap.
/// Returns a new treap that is the union of this treap and an[other] treap.
Treap<T> union(Treap<T> other) => Treap._(_root.union(other._root));

/// Returns a new treap that is the intersection of this treap and another treap.
/// Returns a new treap that is the intersection of this treap and an[other] treap.
Treap<T> intersection(Treap<T> other) =>
Treap._(_root.intersection(other._root));

/// Returns a new treap that is the difference of this treap and another treap.
/// Returns a new treap that is the difference of this treap and an[other] treap.
Treap<T> difference(Treap<T> other) => Treap._(_root.difference(other._root));

/// Operator overloading for adding an item to the treap. Returns a new treap with
/// the added item.
/// Operator overload for [add]ing an [item] to the treap.
Treap<T> operator +(T item) => add(item);

/// Operator overloading for the union of this treap and another treap.
/// Returns a new treap that is the union of the two treaps.
/// Operator overload for the [union] of two treaps.
Treap<T> operator |(Treap<T> other) => union(other);

/// Operator overloading for the intersection of this treap and another treap.
/// Returns a new treap that is the intersection of the two treaps.
/// Operator overload for the [intersection] of two treaps.
Treap<T> operator &(Treap<T> other) => intersection(other);

/// Operator overloading for the difference of this treap and another treap.
/// Returns a new treap that is the difference of the two treaps.
/// Operator overload for the [difference] of two treaps.
Treap<T> operator -(Treap<T> other) => difference(other);

/// Operator overloading for selecting an item in the treap by its rank.
/// Returns the selected item.
T operator [](int i) => select(i);
/// Operator overload for [select]ing an item in the treap by its [rank].
T operator [](int rank) => select(rank);
}

0 comments on commit a17778b

Please sign in to comment.