A self-balancing binary AVL tree written in Zig.
To use this library, you need at least Zig 0.13.x.
// create tree type:
pub const Options = struct {
countChildren: bool = false,
};
pub fn TreeWithOptions(comptime K: type, comptime V: type, comptime Cmp: fn (a: K, b: K) math.Order, comptime options: Options) type
pub fn Tree(comptime K: type, comptime V: type, comptime Cmp: fn (a: K, b: K) math.Order) type
// init/deinit:
pub const InitOptions = struct {
allowFastDeinit: enum { always, auto, never } = .never,
};
pub fn init(a: std.mem.Allocator) Self
pub fn initWithOptions(a: std.mem.Allocator, io: InitOptions) Self
pub fn deinit()
// insert:
pub fn insert(self: *Self, k: K, v: V) !InsertResult
pub fn getOrInsert(self: *Self, k: K, v: V) !InsertResult
pub fn getOrEmplace(self: *Self, k: K, ctor: fn (v: *V, args: anytype) void, args: anytype) !InsertResult
// delete:
pub fn delete(self: *Self, k: K) ?V
pub fn deleteIterator(self: *Self, it: Iterator) Iterator
// find:
pub fn getMin(self: *Self) ?Entry
pub fn getMax(self: *Self) ?Entry
pub fn get(self: *Self, k: K) ?*V
// array-style access:
pub fn at(self: *Self, pos: usize) Entry
pub fn deleteAt(self: *Self, pos: usize) KV
// iterate:
pub fn ascendFromStart(self: *Self) Iterator
pub fn ascendAt(self: *Self, pos: usize) Iterator
pub fn descendFromEnd(self: *Self) Iterator
Example:
const std = @import("std");
const math = std.math;
const zigavl = @import("zigavl");
fn i64Cmp(a: i64, b: i64) math.Order {
return math.order(a, b);
}
pub fn main() !void {
var gpa = std.heap.GeneralPurposeAllocator(.{}){};
defer _ = gpa.detectLeaks();
// first, create an i64-->i64 tree
const TreeType = zigavl.TreeWithOptions(i64, i64, i64Cmp, .{ .countChildren = true });
var t = TreeType.init(gpa.allocator());
defer t.deinit();
// add some elements
var i: i64 = 10;
while (i >= 0) {
_ = try t.insert(i, i);
i -= 1;
}
// get min and max
if (t.getMin().?.k != 0) {
@panic("bad min");
}
if (t.getMax().?.k != 10) {
@panic("bad max");
}
// get an element by it's key
if (t.get(5).?.* != 5) {
@panic("invalid get result");
}
// iterate
var it = t.ascendFromStart();
i = 0;
while (it.value()) |e| {
if (e.k != i) {
@panic("invalid key");
}
if (e.v.* != i) {
@panic("invalid value");
}
i += 1;
it.next();
}
//delete iterator
var second_it = t.deleteIterator(t.ascendFromStart());
if (second_it.value().?.k != 1 or second_it.value().?.v.* != 1) {
@panic("invalid deleteIterator result");
}
// delete by key
if (t.delete(1).? != 1) {
@panic("invalid delete result");
}
// delete by position
const kv = t.deleteAt(0);
if (kv.Key != 2 or kv.Value != 2) {
@panic("invalid deleteAt result");
}
// ascend from pos.
it = t.ascendAt(3);
if (it.value()) |val| {
if (val.k != 6) {
@panic("invalid key");
}
} else {
@panic("invalid iterator");
}
}
Source code is available under the Apache License Version 2.0.