Mercurial > projects > aid
comparison trunk/aid/containers/heap.d @ 0:4b2e8e8a633e
Repository setup.
author | revcompgeek |
---|---|
date | Mon, 03 Mar 2008 19:28:10 -0700 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:4b2e8e8a633e |
---|---|
1 /*++++++++++++++++++++++++++++++++++++++++++++ | |
2 + Heap sorted array + | |
3 + By Matt Peterson + | |
4 ++++++++++++++++++++++++++++++++++++++++++++*/ | |
5 | |
6 /*class Heap(Value) { | |
7 Value[] array; | |
8 int tail; | |
9 public int capacity(){ | |
10 // This returns the current capacity of the heap. | |
11 return array.length; | |
12 } | |
13 public int size(){ | |
14 // This returns the number of items in the heap. | |
15 return tail; | |
16 } | |
17 | |
18 void capacity(int c){ | |
19 // This sets the capacity to c. | |
20 if(c < tail) c = tail; | |
21 array.length = c; | |
22 } | |
23 void insert(Value v){ | |
24 // Inserts a value and sorts it to it's correct position. | |
25 if(tail >= size()) capacity(size()+10); | |
26 array[++tail] = v; | |
27 int i = tail; | |
28 while(i > 0 && array[i/2] > array[i]){ | |
29 array[i] = array[i/2]; | |
30 array[i/2] = v; | |
31 i /= 2; | |
32 } | |
33 } | |
34 Value removeHead(){ | |
35 Value ret = array[0]; | |
36 array[0] = array[tail]; | |
37 tail--; | |
38 i = 0; | |
39 while( | |
40 } | |
41 | |
42 }*/ | |
43 | |
44 struct Heap(Value, Alloc = GCAllocator) { | |
45 | |
46 alias ArrayHeap ContainerType; | |
47 alias Value ValueType; | |
48 alias size_t IndexType; | |
49 | |
50 Value[] data; ///< backing array. null by default, grows as needed | |
51 | |
52 invariant { | |
53 assert( tail <= data.length ); | |
54 } | |
55 | |
56 /** signature for a custom comparison function */ | |
57 alias int delegate(Value* a, Value* b) CompareFcn; | |
58 | |
59 /** Set custom comparison function. */ | |
60 void compareFcn(CompareFcn cmp) { | |
61 cmpFcn = cmp; | |
62 } | |
63 | |
64 /** Get heap contents as dynamic array slice of backing array. */ | |
65 Value[] values() { | |
66 return data[0..tail]; | |
67 } | |
68 | |
69 /** Adds an item to the heap. Increases capacity if needed. */ | |
70 void addTail(Value v) { | |
71 capacity(tail+1); | |
72 data[tail++] = v; | |
73 fixupTail(); | |
74 } | |
75 | |
76 /** Removes and returns the head item of the heap. If the target | |
77 * heap is empty an IndexOutOfBoundsException is thrown unless | |
78 * version=MinTLNoIndexChecking is set. | |
79 */ | |
80 Value takeHead() { | |
81 version (MinTLNoIndexChecking) { | |
82 // no error checking | |
83 } else { | |
84 if (tail == 0) | |
85 throw new IndexOutOfBoundsException(); | |
86 } | |
87 Value val = data[0]; | |
88 data[0] = data[--tail]; | |
89 data[tail] = Value.init; | |
90 fixupHead(); | |
91 return val; | |
92 } | |
93 | |
94 /** Removes the head item of the heap. */ | |
95 void removeHead() { | |
96 version (MinTLNoIndexChecking) { | |
97 // no error checking | |
98 } else { | |
99 if (tail == 0) | |
100 throw new IndexOutOfBoundsException(); | |
101 } | |
102 data[0] = data[--tail]; | |
103 data[tail] = Value.init; | |
104 fixupHead(); | |
105 } | |
106 | |
107 /** Get the length of heap. */ | |
108 size_t length() { | |
109 return tail; | |
110 } | |
111 | |
112 /** Test if container is empty. */ | |
113 bool isEmpty() { | |
114 return tail == 0; | |
115 } | |
116 | |
117 /** Clear all contents. */ | |
118 void clear() { | |
119 static if (is(Alloc == GCAllocator)) { | |
120 } else { | |
121 if (data.ptr) | |
122 Alloc.gcFree(data.ptr); | |
123 } | |
124 *this = ArrayHeap.init; | |
125 } | |
126 | |
127 /** Get the nth item in the heap from head. */ | |
128 Value opIndex(size_t n) { | |
129 return data[n]; | |
130 } | |
131 | |
132 /** Get a pointer to the nth item in the heap */ | |
133 Value* lookup(size_t n) { | |
134 return &data[n]; | |
135 } | |
136 | |
137 /** Set the nth item in the heap. */ | |
138 void opIndexAssign(Value val, size_t n) { | |
139 data[n] = val; | |
140 } | |
141 | |
142 /** Duplicates a heap. */ | |
143 ArrayHeap dup() { | |
144 ArrayHeap res; | |
145 static if (is(Alloc == GCAllocator)) { | |
146 res.data = data.dup; | |
147 } else { | |
148 Value* p = cast(Value*)Alloc.malloc(data.length * Value.sizeof); | |
149 res.data = p[0 .. data.length]; | |
150 res.data[] = data[]; | |
151 } | |
152 res.tail = tail; | |
153 res.cmpFcn = cmpFcn; | |
154 return res; | |
155 } | |
156 | |
157 /** Test for equality of two heaps. */ | |
158 int opEquals(ArrayHeap c) { | |
159 size_t len = length; | |
160 if (len !is c.length) | |
161 return 0; | |
162 size_t a,b; | |
163 a = 0; | |
164 b = 0; | |
165 TypeInfo ti = typeid(Value); | |
166 for (size_t k = 0; k < len; k++) { | |
167 if (!ti.equals(&data[a],&c.data[b])) | |
168 return 0; | |
169 a++; | |
170 b++; | |
171 } | |
172 return 1; | |
173 } | |
174 | |
175 /** Compare two heaps. */ | |
176 int opCmp(ArrayHeap c) { | |
177 size_t len = length; | |
178 if (len > c.length) | |
179 len = c.length; | |
180 size_t a,b; | |
181 a = 0; | |
182 b = 0; | |
183 TypeInfo ti = typeid(Value); | |
184 for (size_t k = 0; k < len; k++) { | |
185 int cmp = ti.compare(&data[a],&c.data[b]); | |
186 if (cmp) | |
187 return cmp; | |
188 a++; | |
189 b++; | |
190 } | |
191 return cast(int)length - cast(int)c.length; | |
192 } | |
193 | |
194 /** Returns a short string representation of the heap. */ | |
195 char[] toString() { | |
196 return "[ArrayHeap length " ~ std.string.toString(tail) ~ "]"; | |
197 } | |
198 | |
199 /** Iterates over the heap from head to tail calling delegate to | |
200 * perform an action. The value is passed to the delegate. | |
201 */ | |
202 int opApplyNoKey(int delegate(inout Value x) dg){ | |
203 int res = 0; | |
204 for (size_t k=0; k < tail; k++) { | |
205 res = dg(data[k]); | |
206 if (res) break; | |
207 } | |
208 return res; | |
209 } | |
210 | |
211 /** Iterates over the heap from head to tail calling delegate to | |
212 * perform an action. The index from 0 and the value are passed | |
213 * to the delegate. | |
214 */ | |
215 int opApplyWithKey(int delegate(inout size_t n, inout Value x) dg){ | |
216 int res = 0; | |
217 for (size_t k=0; k < tail; k++) { | |
218 res = dg(k,data[k]); | |
219 if (res) break; | |
220 } | |
221 return res; | |
222 } | |
223 | |
224 alias opApplyNoKey opApply; | |
225 alias opApplyWithKey opApply; | |
226 | |
227 /** Ensure the minimum capacity of heap. */ | |
228 void capacity(size_t cap) { | |
229 if (cap > data.length) { | |
230 cap = (cap+1)*2; | |
231 static if (is(Alloc == GCAllocator)) { | |
232 data.length = cap; | |
233 } else { | |
234 Value* p = data.ptr; | |
235 p = cast(Value*)Alloc.gcRealloc(p,cap*Value.sizeof); | |
236 p[data.length .. cap] = Value.init; | |
237 data = p[0 .. cap]; | |
238 } | |
239 } | |
240 } | |
241 | |
242 // Helper functions | |
243 | |
244 // enforce heap invariant after a new head | |
245 private void fixupHead() { | |
246 size_t n = 0; | |
247 TypeInfo ti = typeid(Value); | |
248 if (cmpFcn is null) { | |
249 cmpFcn = cast(CompareFcn)&ti.compare; | |
250 } | |
251 for (;;) { | |
252 size_t n1 = 2*n+1; | |
253 if (n1 >= tail) break; | |
254 if ((n1 != tail-1) && (cmpFcn(&data[n1],&data[n1+1]) < 0)) | |
255 n1++; | |
256 if (cmpFcn(&data[n],&data[n1]) < 0) { | |
257 ti.swap(&data[n],&data[n1]); | |
258 n = n1; | |
259 } else { | |
260 break; | |
261 } | |
262 } | |
263 } | |
264 | |
265 // enforce heap invariant after a new tail | |
266 private void fixupTail() { | |
267 size_t n = tail-1; | |
268 TypeInfo ti = typeid(Value); | |
269 if (cmpFcn is null) { | |
270 cmpFcn = cast(CompareFcn)&ti.compare; | |
271 } | |
272 size_t n1 = (n-1)>>1; | |
273 while ((n > 0) && (cmpFcn(&data[n],&data[n1]) > 0)) { | |
274 ti.swap(&data[n],&data[n1]); | |
275 n = n1; | |
276 n1 = (n-1)>>1; | |
277 } | |
278 } | |
279 | |
280 private CompareFcn cmpFcn; | |
281 private size_t tail; | |
282 } |