Skip to content

Commit eb66d31

Browse files
thestingerbrson
authored andcommitted
---
yaml --- r: 36762 b: refs/heads/try2 c: dd2b32b h: refs/heads/master v: v3
1 parent 8ed6e61 commit eb66d31

File tree

3 files changed

+255
-1
lines changed

3 files changed

+255
-1
lines changed

[refs]

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ refs/heads/snap-stage3: eb8fd119c65c67f3b1b8268cc7341c22d39b7b61
55
refs/heads/try: d324a424d8f84b1eb049b12cf34182bda91b0024
66
refs/tags/release-0.1: 1f5c5126e96c79d22cb7862f75304136e204f105
77
refs/heads/ndm: f3868061cd7988080c30d6d5bf352a5a5fe2460b
8-
refs/heads/try2: 6036add5ebf18f412adf8a9d36db738906acc274
8+
refs/heads/try2: dd2b32be56945824e1e900d9748274633d6db6c1
99
refs/heads/incoming: d9317a174e434d4c99fc1a37fd7dc0d2f5328d37
1010
refs/heads/dist-snap: 22efa39382d41b084fde1719df7ae8ce5697d8c9
1111
refs/tags/release-0.2: c870d2dffb391e14efb05aa27898f1f6333a9596
Lines changed: 253 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,253 @@
1+
2+
/// A priority queue implemented with a binary heap
3+
use core::cmp::Ord;
4+
5+
pub struct PriorityQueue <T: Copy Ord>{
6+
priv data: ~[T],
7+
}
8+
9+
impl <T: Copy Ord> PriorityQueue<T> {
10+
/// Returns the greatest item in the queue - fails if empty
11+
pure fn top(&self) -> T { self.data[0] }
12+
13+
/// Returns the greatest item in the queue - None if empty
14+
pure fn maybe_top(&self) -> Option<T> {
15+
if self.is_empty() { None } else { Some(self.top()) }
16+
}
17+
18+
/// Returns the length of the queue
19+
pure fn len(&self) -> uint { self.data.len() }
20+
21+
/// Returns true if a queue contains no elements
22+
pure fn is_empty(&self) -> bool { self.data.is_empty() }
23+
24+
/// Returns true if a queue contains some elements
25+
pure fn is_not_empty(&self) -> bool { self.data.is_not_empty() }
26+
27+
/// Returns the number of elements the queue can hold without reallocating
28+
pure fn capacity(&self) -> uint { vec::capacity(&self.data) }
29+
30+
fn reserve(&mut self, n: uint) { vec::reserve(&mut self.data, n) }
31+
32+
fn reserve_at_least(&mut self, n: uint) {
33+
vec::reserve_at_least(&mut self.data, n)
34+
}
35+
36+
/// Drop all items from the queue
37+
fn clear(&mut self) { self.data.truncate(0) }
38+
39+
/// Pop the greatest item from the queue - fails if empty
40+
fn pop(&mut self) -> T {
41+
let last = self.data.pop();
42+
if self.is_not_empty() {
43+
let ret = self.data[0];
44+
self.data[0] = last;
45+
self.siftup(0);
46+
ret
47+
} else { last }
48+
}
49+
50+
/// Pop the greatest item from the queue - None if empty
51+
fn maybe_pop(&mut self) -> Option<T> {
52+
if self.is_empty() { None } else { Some(self.pop()) }
53+
}
54+
55+
/// Push an item onto the queue
56+
fn push(&mut self, item: T) {
57+
self.data.push(item);
58+
self.siftdown(0, self.len() - 1);
59+
}
60+
61+
/// Optimized version of a push followed by a pop
62+
fn push_pop(&mut self, item: T) -> T {
63+
let mut item = item;
64+
if self.is_not_empty() && self.data[0] > item {
65+
item <-> self.data[0];
66+
self.siftup(0);
67+
}
68+
item
69+
}
70+
71+
/// Optimized version of a pop followed by a push - fails if empty
72+
fn replace(&mut self, item: T) -> T {
73+
let ret = self.data[0];
74+
self.data[0] = item;
75+
self.siftup(0);
76+
ret
77+
}
78+
79+
priv fn siftdown(&mut self, startpos: uint, pos: uint) {
80+
let mut pos = pos;
81+
let newitem = self.data[pos];
82+
83+
while pos > startpos {
84+
let parentpos = (pos - 1) >> 1;
85+
let parent = self.data[parentpos];
86+
if newitem > parent {
87+
self.data[pos] = parent;
88+
pos = parentpos;
89+
loop
90+
}
91+
break
92+
}
93+
self.data[pos] = newitem;
94+
}
95+
96+
priv fn siftup_range(&mut self, pos: uint, endpos: uint) {
97+
let mut pos = pos;
98+
let startpos = pos;
99+
let newitem = self.data[pos];
100+
101+
let mut childpos = 2 * pos + 1;
102+
while childpos < endpos {
103+
let rightpos = childpos + 1;
104+
if rightpos < endpos &&
105+
!(self.data[childpos] > self.data[rightpos]) {
106+
childpos = rightpos;
107+
}
108+
self.data[pos] = self.data[childpos];
109+
pos = childpos;
110+
childpos = 2 * pos + 1;
111+
}
112+
self.data[pos] = newitem;
113+
self.siftdown(startpos, pos);
114+
}
115+
116+
priv fn siftup(&mut self, pos: uint) {
117+
self.siftup_range(pos, self.len());
118+
}
119+
}
120+
121+
/// Consume the PriorityQueue and return the underlying vector
122+
pub pure fn to_vec<T: Copy Ord>(q: PriorityQueue<T>) -> ~[T] {
123+
let PriorityQueue{data: v} = q;
124+
v
125+
}
126+
127+
/// Consume the PriorityQueue and return a vector in sorted (ascending) order
128+
pub pure fn to_sorted_vec<T: Copy Ord>(q: PriorityQueue<T>) -> ~[T] {
129+
let mut q = q;
130+
let mut end = q.len() - 1;
131+
while end > 0 {
132+
q.data[end] <-> q.data[0];
133+
end -= 1;
134+
unsafe { q.siftup_range(0, end) } // purity-checking workaround
135+
}
136+
to_vec(q)
137+
}
138+
139+
pub pure fn from_vec<T: Copy Ord>(xs: ~[T]) -> PriorityQueue<T> {
140+
let mut q = PriorityQueue{data: xs,};
141+
let mut n = q.len() / 2;
142+
while n > 0 {
143+
n -= 1;
144+
unsafe { q.siftup(n) }; // purity-checking workaround
145+
}
146+
q
147+
}
148+
149+
#[cfg(test)]
150+
mod tests {
151+
use sort::merge_sort;
152+
use core::cmp::le;
153+
154+
#[test]
155+
fn test_top_and_pop() {
156+
let data = ~[2, 4, 6, 2, 1, 8, 10, 3, 5, 7, 0, 9, 1];
157+
let mut sorted = merge_sort(data, le);
158+
let mut heap = from_vec(data);
159+
while heap.is_not_empty() {
160+
assert heap.top() == sorted.last();
161+
assert heap.pop() == sorted.pop();
162+
}
163+
}
164+
165+
#[test]
166+
fn test_push() {
167+
let mut heap = from_vec(~[2, 4, 9]);
168+
assert heap.len() == 3;
169+
assert heap.top() == 9;
170+
heap.push(11);
171+
assert heap.len() == 4;
172+
assert heap.top() == 11;
173+
heap.push(5);
174+
assert heap.len() == 5;
175+
assert heap.top() == 11;
176+
heap.push(27);
177+
assert heap.len() == 6;
178+
assert heap.top() == 27;
179+
heap.push(3);
180+
assert heap.len() == 7;
181+
assert heap.top() == 27;
182+
heap.push(103);
183+
assert heap.len() == 8;
184+
assert heap.top() == 103;
185+
}
186+
187+
#[test]
188+
fn test_push_pop() {
189+
let mut heap = from_vec(~[5, 5, 2, 1, 3]);
190+
assert heap.len() == 5;
191+
assert heap.push_pop(6) == 6;
192+
assert heap.len() == 5;
193+
assert heap.push_pop(0) == 5;
194+
assert heap.len() == 5;
195+
assert heap.push_pop(4) == 5;
196+
assert heap.len() == 5;
197+
assert heap.push_pop(1) == 4;
198+
assert heap.len() == 5;
199+
}
200+
201+
#[test]
202+
fn test_replace() {
203+
let mut heap = from_vec(~[5, 5, 2, 1, 3]);
204+
assert heap.len() == 5;
205+
assert heap.replace(6) == 5;
206+
assert heap.len() == 5;
207+
assert heap.replace(0) == 6;
208+
assert heap.len() == 5;
209+
assert heap.replace(4) == 5;
210+
assert heap.len() == 5;
211+
assert heap.replace(1) == 4;
212+
assert heap.len() == 5;
213+
}
214+
215+
#[test]
216+
fn test_to_sorted_vec() {
217+
let data = ~[2, 4, 6, 2, 1, 8, 10, 3, 5, 7, 0, 9, 1];
218+
assert to_sorted_vec(from_vec(data)) == merge_sort(data, le);
219+
}
220+
221+
#[test]
222+
#[should_fail]
223+
fn test_empty_pop() { let mut heap = from_vec::<int>(~[]); heap.pop(); }
224+
225+
#[test]
226+
fn test_empty_maybe_pop() {
227+
let mut heap = from_vec::<int>(~[]);
228+
assert heap.maybe_pop().is_none();
229+
}
230+
231+
#[test]
232+
#[should_fail]
233+
fn test_empty_top() { from_vec::<int>(~[]).top(); }
234+
235+
#[test]
236+
fn test_empty_maybe_top() {
237+
assert from_vec::<int>(~[]).maybe_top().is_none();
238+
}
239+
240+
#[test]
241+
#[should_fail]
242+
fn test_empty_replace() {
243+
let mut heap = from_vec::<int>(~[]);
244+
heap.replace(5);
245+
}
246+
247+
#[test]
248+
fn test_to_vec() {
249+
let data = ~[1, 3, 5, 7, 9, 2, 4, 6, 8, 0];
250+
let heap = from_vec(copy data);
251+
assert merge_sort(to_vec(heap), le) == merge_sort(data, le);
252+
}
253+
}

branches/try2/src/libstd/std.rc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,7 @@ pub mod deque;
7373
pub mod fun_treemap;
7474
pub mod list;
7575
pub mod map;
76+
pub mod priority_queue;
7677
pub mod rope;
7778
pub mod smallintmap;
7879
pub mod sort;

0 commit comments

Comments
 (0)