Skip to content

Commit aa1fbb6

Browse files
committed
docs: add queue examples and benchmarks
1 parent e413070 commit aa1fbb6

10 files changed

Lines changed: 268 additions & 0 deletions

Cargo.toml

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,18 @@ path = "examples/soluciones/stack_balanced_parentheses.rs"
4949
name = "solution_stack_undo_redo"
5050
path = "examples/soluciones/stack_undo_redo.rs"
5151

52+
[[example]]
53+
name = "solution_queue_trace_order"
54+
path = "examples/soluciones/queue_trace_order.rs"
55+
56+
[[example]]
57+
name = "solution_queue_round_robin"
58+
path = "examples/soluciones/queue_round_robin.rs"
59+
60+
[[example]]
61+
name = "solution_queue_filter_ready_jobs"
62+
path = "examples/soluciones/queue_filter_ready_jobs.rs"
63+
5264
[[bench]]
5365
name = "vector_bench"
5466
path = "benches/vector_bench.rs"
@@ -63,3 +75,8 @@ harness = false
6375
name = "stack_bench"
6476
path = "benches/stack_bench.rs"
6577
harness = false
78+
79+
[[bench]]
80+
name = "queue_bench"
81+
path = "benches/queue_bench.rs"
82+
harness = false

benches/queue_bench.rs

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
use rust_data_structures::queue::Queue;
2+
use rust_data_structures::vector::Vector;
3+
use std::hint::black_box;
4+
use std::time::{Duration, Instant};
5+
6+
const SIZE: usize = 30_000;
7+
8+
fn main() {
9+
println!("queue benchmark (manual, std::time::Instant)");
10+
println!("size: {SIZE}");
11+
println!("circular enqueue/dequeue: {:?}", bench_circular_queue());
12+
println!(
13+
"naive vector front remove: {:?}",
14+
bench_naive_vector_queue()
15+
);
16+
println!("wraparound reuse: {:?}", bench_wraparound_reuse());
17+
}
18+
19+
fn bench_circular_queue() -> Duration {
20+
let start = Instant::now();
21+
let mut queue = Queue::new();
22+
23+
for value in 0..SIZE {
24+
queue.enqueue(black_box(value));
25+
}
26+
27+
while let Some(value) = queue.dequeue() {
28+
black_box(value);
29+
}
30+
31+
start.elapsed()
32+
}
33+
34+
fn bench_naive_vector_queue() -> Duration {
35+
let start = Instant::now();
36+
let mut vector = Vector::new();
37+
38+
for value in 0..SIZE {
39+
vector.push(black_box(value));
40+
}
41+
42+
while !vector.is_empty() {
43+
black_box(vector.remove(0));
44+
}
45+
46+
start.elapsed()
47+
}
48+
49+
fn bench_wraparound_reuse() -> Duration {
50+
let start = Instant::now();
51+
let mut queue = Queue::with_capacity(128);
52+
53+
for value in 0..SIZE {
54+
queue.enqueue(black_box(value));
55+
if value % 2 == 0 {
56+
black_box(queue.dequeue());
57+
}
58+
}
59+
60+
while let Some(value) = queue.dequeue() {
61+
black_box(value);
62+
}
63+
64+
start.elapsed()
65+
}

diagrams/04-queue.mmd

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
flowchart LR
2+
title["Queue: FIFO con buffer circular"]
3+
4+
subgraph metadata["Metadatos"]
5+
head["head = 2"]
6+
len["len = 4"]
7+
cap["capacity = 6"]
8+
end
9+
10+
subgraph buffer["Buffer físico"]
11+
slot0["0: D"]
12+
slot1["1: libre"]
13+
slot2["2: A (front)"]
14+
slot3["3: B"]
15+
slot4["4: C"]
16+
slot5["5: libre"]
17+
end
18+
19+
head --> slot2
20+
len --> slot0
21+
cap --> slot5
22+
23+
dequeue["dequeue()<br/>toma front y avanza head"]
24+
enqueue["enqueue(E)<br/>escribe en (head + len) % capacity"]
25+
26+
dequeue --> head
27+
enqueue --> slot1

examples/queue_advanced.rs

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
use rust_data_structures::queue::Queue;
2+
3+
fn main() {
4+
let mut queue = Queue::with_capacity(3);
5+
6+
queue.enqueue("A");
7+
queue.enqueue("B");
8+
queue.enqueue("C");
9+
queue.dequeue();
10+
queue.dequeue();
11+
queue.enqueue("D");
12+
queue.enqueue("E");
13+
14+
println!("capacidad: {}", queue.capacity());
15+
println!(
16+
"orden logico: {:?}",
17+
queue.iter().copied().collect::<Vec<_>>()
18+
);
19+
}

examples/queue_basic.rs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
use rust_data_structures::queue::Queue;
2+
3+
fn main() {
4+
let mut queue = Queue::new();
5+
6+
queue.enqueue("primer estudiante");
7+
queue.enqueue("segundo estudiante");
8+
queue.enqueue("tercer estudiante");
9+
10+
println!("siguiente: {}", queue.front().unwrap());
11+
println!("atendido: {}", queue.dequeue().unwrap());
12+
}

examples/queue_intermediate.rs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
use rust_data_structures::queue::Queue;
2+
3+
fn main() {
4+
let mut jobs = Queue::new();
5+
6+
jobs.enqueue("generar docs");
7+
jobs.enqueue("correr tests");
8+
jobs.enqueue("publicar reporte");
9+
10+
while let Some(job) = jobs.dequeue() {
11+
println!("procesando: {job}");
12+
}
13+
}

examples/queue_real_case.rs

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
use rust_data_structures::queue::Queue;
2+
3+
fn main() {
4+
let mut requests = Queue::new();
5+
6+
requests.enqueue(Request::new("/courses", 10));
7+
requests.enqueue(Request::new("/courses/rust-data-structures", 12));
8+
requests.enqueue(Request::new("/health", 1));
9+
10+
while let Some(request) = requests.dequeue() {
11+
println!("{} ({} ms)", request.path, request.estimated_ms);
12+
}
13+
}
14+
15+
struct Request {
16+
path: &'static str,
17+
estimated_ms: u32,
18+
}
19+
20+
impl Request {
21+
fn new(path: &'static str, estimated_ms: u32) -> Self {
22+
Self { path, estimated_ms }
23+
}
24+
}
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
use rust_data_structures::queue::Queue;
2+
3+
fn main() {
4+
let mut queue = Queue::new();
5+
queue.enqueue(Job::new("index", true));
6+
queue.enqueue(Job::new("email", false));
7+
queue.enqueue(Job::new("report", true));
8+
9+
let ready = drain_ready(queue);
10+
11+
assert_eq!(ready, vec!["index", "report"]);
12+
println!("{ready:?}");
13+
}
14+
15+
fn drain_ready(mut queue: Queue<Job>) -> Vec<&'static str> {
16+
let mut ready = Vec::new();
17+
18+
while let Some(job) = queue.dequeue() {
19+
if job.ready {
20+
ready.push(job.name);
21+
}
22+
}
23+
24+
ready
25+
}
26+
27+
struct Job {
28+
name: &'static str,
29+
ready: bool,
30+
}
31+
32+
impl Job {
33+
fn new(name: &'static str, ready: bool) -> Self {
34+
Self { name, ready }
35+
}
36+
}
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
use rust_data_structures::queue::Queue;
2+
3+
fn main() {
4+
let mut queue = Queue::new();
5+
queue.enqueue(Task::new("docs", 2));
6+
queue.enqueue(Task::new("tests", 1));
7+
8+
let completed = run_round_robin(queue);
9+
10+
assert_eq!(completed, vec!["tests", "docs"]);
11+
println!("{completed:?}");
12+
}
13+
14+
fn run_round_robin(mut queue: Queue<Task>) -> Vec<&'static str> {
15+
let mut completed = Vec::new();
16+
17+
while let Some(mut task) = queue.dequeue() {
18+
task.remaining -= 1;
19+
20+
if task.remaining == 0 {
21+
completed.push(task.name);
22+
} else {
23+
queue.enqueue(task);
24+
}
25+
}
26+
27+
completed
28+
}
29+
30+
struct Task {
31+
name: &'static str,
32+
remaining: u8,
33+
}
34+
35+
impl Task {
36+
fn new(name: &'static str, remaining: u8) -> Self {
37+
Self { name, remaining }
38+
}
39+
}
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
use rust_data_structures::queue::Queue;
2+
3+
fn main() {
4+
let mut queue = Queue::new();
5+
let mut trace = Vec::new();
6+
7+
queue.enqueue("A");
8+
queue.enqueue("B");
9+
trace.push(queue.dequeue());
10+
queue.enqueue("C");
11+
trace.push(queue.dequeue());
12+
trace.push(queue.dequeue());
13+
14+
assert_eq!(trace, vec![Some("A"), Some("B"), Some("C")]);
15+
println!("{trace:?}");
16+
}

0 commit comments

Comments
 (0)