aboutsummaryrefslogtreecommitdiff
path: root/lib/std/rb.zig
diff options
context:
space:
mode:
authorShawn Landden <shawn@git.icu>2020-01-19 22:10:21 +0400
committerShawn Landden <shawn@git.icu>2020-01-19 22:10:21 +0400
commit4ab9678b9553d77bc0683ee69a8936524f6a7808 (patch)
treea85c01160e6ae980c77b6e6a54645679cf21a1e1 /lib/std/rb.zig
parente19008292222d37b3a08a4e6a9d41553ecfcfd7e (diff)
downloadzig-4ab9678b9553d77bc0683ee69a8936524f6a7808.tar.gz
zig-4ab9678b9553d77bc0683ee69a8936524f6a7808.zip
rb: add sort() that re-sorts tree with new compare function
You can also specify the same compare function, but after updating the context that the function will use (connected to the rb.Tree) before.
Diffstat (limited to 'lib/std/rb.zig')
-rw-r--r--lib/std/rb.zig23
1 files changed, 23 insertions, 0 deletions
diff --git a/lib/std/rb.zig b/lib/std/rb.zig
index 0fefa033a9..78e1e3aedd 100644
--- a/lib/std/rb.zig
+++ b/lib/std/rb.zig
@@ -134,6 +134,20 @@ pub const Tree = struct {
root: ?*Node,
compareFn: fn (*Node, *Node, *Tree) Order,
+ /// Re-sorts a tree with a new compare function
+ pub fn sort(tree: *Tree, newCompareFn: fn (*Node, *Node, *Tree) Order) !void {
+ var newTree = Tree.init(newCompareFn);
+ var node: *Node = undefined;
+ while (true) {
+ node = tree.first() orelse break;
+ tree.remove(node);
+ if (newTree.insert(node) != null) {
+ return error.NotUnique; // EEXISTS
+ }
+ }
+ tree.* = newTree;
+ }
+
/// If you have a need for a version that caches this, please file a bug.
pub fn first(tree: *Tree) ?*Node {
var node: *Node = tree.root orelse return null;
@@ -244,6 +258,7 @@ pub const Tree = struct {
return doLookup(key, tree, &parent, &is_left);
}
+ /// If node is not part of tree, behavior is undefined.
pub fn remove(tree: *Tree, nodeconst: *Node) void {
var node = nodeconst;
// as this has the same value as node, it is unsafe to access node after newnode
@@ -514,6 +529,10 @@ fn testCompare(l: *Node, r: *Node, contextIgnored: *Tree) Order {
unreachable;
}
+fn testCompareReverse(l: *Node, r: *Node, contextIgnored: *Tree) Order {
+ return testCompare(r, l, contextIgnored);
+}
+
test "rb" {
if (@import("builtin").arch == .aarch64) {
// TODO https://github.com/ziglang/zig/issues/3288
@@ -600,4 +619,8 @@ test "multiple inserts, followed by calling first and last" {
var lookupNode: testNumber = undefined;
lookupNode.value = 3;
assert(tree.lookup(&lookupNode.node) == &third.node);
+ tree.sort(testCompareReverse) catch unreachable;
+ assert(testGetNumber(tree.first().?).value == 3);
+ assert(testGetNumber(tree.last().?).value == 0);
+ assert(tree.lookup(&lookupNode.node) == &third.node);
}