mirror of
https://github.com/odin-lang/Odin.git
synced 2026-06-08 11:34:20 +00:00
[core:container/priority_queue] Add example and tests
This commit is contained in:
50
core/container/priority_queue/doc.odin
Normal file
50
core/container/priority_queue/doc.odin
Normal file
@@ -0,0 +1,50 @@
|
||||
// A priority queue data structure.
|
||||
package container_priority_queue
|
||||
|
||||
/*
|
||||
import "base:runtime"
|
||||
import pq "core:container/priority_queue"
|
||||
|
||||
main :: proc() {
|
||||
Printer_Job :: struct {
|
||||
user_id: u64,
|
||||
weight: enum u8 {Highest, High, Normal, Low, Idle},
|
||||
}
|
||||
|
||||
q: pq.Priority_Queue(Printer_Job)
|
||||
pq.init(
|
||||
pq = &q,
|
||||
less = proc(a, b: Printer_Job) -> bool {
|
||||
// Jobs will be sorted in order of increasing weight
|
||||
return a.weight < b.weight
|
||||
},
|
||||
swap = pq.default_swap_proc(Printer_Job),
|
||||
)
|
||||
defer pq.destroy(&q)
|
||||
|
||||
// Add jobs with random weights
|
||||
for _ in 0..<100 {
|
||||
job: Printer_Job = ---
|
||||
assert(runtime.random_generator_read_ptr(context.random_generator, &job, size_of(job)))
|
||||
pq.push(&q, job)
|
||||
}
|
||||
|
||||
last: Printer_Job
|
||||
for pq.len(q) > 0 {
|
||||
// Drain jobs
|
||||
v := pq.pop(&q)
|
||||
assert(v.weight >= last.weight)
|
||||
last = v
|
||||
}
|
||||
|
||||
// Queue empty?
|
||||
assert(pq.len(q) == 0)
|
||||
|
||||
// Add one more job
|
||||
pq.push(&q, Printer_Job{user_id = 42, weight = .Idle})
|
||||
|
||||
// Cancel all jobs
|
||||
pq.clear(&q)
|
||||
assert(pq.len(q) == 0)
|
||||
}
|
||||
*/
|
||||
@@ -1,9 +1,11 @@
|
||||
// A priority queue data structure.
|
||||
package container_priority_queue
|
||||
|
||||
import "base:builtin"
|
||||
import "base:runtime"
|
||||
|
||||
// Priority Queue.
|
||||
//
|
||||
// Important: Must be `init`ialized with `less` and `swap` procedures before use. See `doc.odin` for an example.
|
||||
Priority_Queue :: struct($T: typeid) {
|
||||
queue: [dynamic]T,
|
||||
|
||||
|
||||
113
tests/core/container/test_core_priority_queue.odin
Normal file
113
tests/core/container/test_core_priority_queue.odin
Normal file
@@ -0,0 +1,113 @@
|
||||
package test_core_container
|
||||
|
||||
import "base:runtime"
|
||||
import pq "core:container/priority_queue"
|
||||
import "core:math/rand"
|
||||
import "core:testing"
|
||||
|
||||
@test
|
||||
test_priority_queue :: proc(t: ^testing.T) {
|
||||
q: pq.Priority_Queue(int)
|
||||
pq.init(&q, proc(a, b: int) -> bool {
|
||||
return a < b
|
||||
}, pq.default_swap_proc(int))
|
||||
defer pq.destroy(&q)
|
||||
|
||||
assert(pq.cap(q) == pq.DEFAULT_CAPACITY)
|
||||
|
||||
pq.push(&q, 42)
|
||||
assert(pq.len(q) == 1)
|
||||
assert(pq.peek(q) == 42)
|
||||
|
||||
v := pq.pop(&q)
|
||||
assert(v == 42)
|
||||
assert(pq.len(q) == 0)
|
||||
|
||||
ok: bool
|
||||
v, ok = pq.peek_safe(q)
|
||||
assert(v == 0 && ok == false)
|
||||
|
||||
v, ok = pq.pop_safe(&q)
|
||||
assert(v == 0 && ok == false)
|
||||
|
||||
N :: 15
|
||||
for _ in 0..<N {
|
||||
v = int(rand.int63())
|
||||
pq.push(&q, v)
|
||||
}
|
||||
|
||||
assert(pq.len(q) == N)
|
||||
|
||||
last := 0
|
||||
for pq.len(q) > 0 {
|
||||
v = pq.pop(&q)
|
||||
assert(v >= last)
|
||||
last = v
|
||||
}
|
||||
|
||||
vals := []int{6, 15, 3, 9, 12}
|
||||
for _v in vals {
|
||||
pq.push(&q, _v)
|
||||
}
|
||||
// Break ordering and fix it
|
||||
q.queue[3] = 42
|
||||
pq.fix(&q, 3)
|
||||
|
||||
last = 0
|
||||
for pq.len(q) > 0 {
|
||||
v = pq.pop(&q)
|
||||
assert(v >= last)
|
||||
last = v
|
||||
}
|
||||
|
||||
assert(pq.len(q) == 0)
|
||||
|
||||
for _v in vals {
|
||||
pq.push(&q, _v)
|
||||
}
|
||||
|
||||
// Break ordering again, but this time delete that index
|
||||
q.queue[3] = 42
|
||||
v, ok = pq.remove(&q, 3)
|
||||
assert(v == 42 && ok == true)
|
||||
|
||||
last = 0
|
||||
for pq.len(q) > 0 {
|
||||
v = pq.pop(&q)
|
||||
assert(v >= last && v != 42)
|
||||
last = v
|
||||
}
|
||||
}
|
||||
|
||||
@(test)
|
||||
test_pq_init_from_dynamic_array :: proc(t: ^testing.T) {
|
||||
N :: 50_000
|
||||
|
||||
arr := make_dynamic_array_len_cap([dynamic]u64, N, N, context.allocator)
|
||||
assert(runtime.random_generator_read_ptr(context.random_generator, raw_data(arr), N * size_of(u64)))
|
||||
|
||||
q: pq.Priority_Queue(u64)
|
||||
pq.init_from_dynamic_array(
|
||||
pq = &q,
|
||||
queue = arr,
|
||||
less = proc(a, b: u64) -> bool { return a < b },
|
||||
swap = pq.default_swap_proc(u64),
|
||||
)
|
||||
defer pq.destroy(&q)
|
||||
|
||||
assert(pq.len(q) == N)
|
||||
|
||||
last: u64
|
||||
for pq.len(q) > 0 {
|
||||
v := pq.pop(&q)
|
||||
assert(v >= last)
|
||||
last = v
|
||||
}
|
||||
|
||||
assert(pq.len(q) == 0)
|
||||
assert(pq.cap(q) == N)
|
||||
|
||||
pq.reserve(&q, N + 12)
|
||||
assert(pq.cap(q) == N + 12)
|
||||
|
||||
}
|
||||
@@ -3,13 +3,13 @@ package test_core_container
|
||||
import "core:container/xar"
|
||||
import "core:testing"
|
||||
|
||||
Value :: struct {
|
||||
v: int,
|
||||
p: ^int,
|
||||
}
|
||||
|
||||
@test
|
||||
test_xar_pointer_stability :: proc(t: ^testing.T) {
|
||||
Value :: struct {
|
||||
v: int,
|
||||
p: ^int,
|
||||
}
|
||||
|
||||
x: xar.Array(int, 4)
|
||||
defer xar.destroy(&x)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user