aboutsummaryrefslogtreecommitdiff
path: root/src/heap.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/heap.c')
-rw-r--r--src/heap.c291
1 files changed, 291 insertions, 0 deletions
diff --git a/src/heap.c b/src/heap.c
new file mode 100644
index 0000000..091e761
--- /dev/null
+++ b/src/heap.c
@@ -0,0 +1,291 @@
1#include <assert.h>
2#include <stdbool.h>
3#include <stdio.h>
4#include <stdlib.h>
5#include <time.h>
6
7#include "util.h"
8
9typedef int T;
10
11// https://stackoverflow.com/a/22900767
12
13#define LEFT(idx) (idx * 2 + 1)
14#define RIGHT(idx) (idx * 2 + 2)
15#define PARENT(idx) ((idx - 1) / 2)
16
17static void
18swap(T heap[], size_t i, size_t j)
19{
20 T temp = heap[i];
21 heap[i] = heap[j];
22 heap[j] = temp;
23}
24
25#define MAX_HEAP 1
26
27#if defined(MAX_HEAP)
28// MAX-HEAP Implementation
29static void
30fixup(T heap[], size_t i)
31{
32 size_t p = PARENT(i);
33
34 while ( i > 0 && heap[p] < heap[i] ) {
35 swap(heap, p, i);
36
37 i = p;
38 p = PARENT(i);
39 }
40}
41
42static void
43fixdown(T heap[], size_t i, size_t n)
44{
45 for ( ;; ) {
46 const size_t l = LEFT(i);
47 const size_t r = RIGHT(i);
48 size_t m = i;
49
50 if ( l < n && heap[m] < heap[l] ) {
51 m = l;
52 }
53
54 if ( r < n && heap[m] < heap[r] ) {
55 m = r;
56 }
57
58 if ( m == i ) {
59 break;
60 }
61
62 swap(heap, m, i);
63
64 i = m;
65 }
66}
67
68static bool
69is_heap(T heap[], size_t n)
70{
71 for ( size_t i = 0; i < n / 2; ++i ) {
72 const size_t l = LEFT(i);
73 const size_t r = RIGHT(i);
74
75 if ( l < n && heap[i] < heap[l] ) {
76 return false;
77 }
78 if ( r < n && heap[i] < heap[r] ) {
79 return false;
80 }
81 }
82 return true;
83}
84
85#else
86// MIN-HEAP Implementation
87static void
88fixup(T heap[], size_t i)
89{
90 size_t p = PARENT(i);
91
92 while ( i > 0 && heap[i] < heap[p] ) {
93 swap(heap, i, p);
94
95 i = p;
96 p = PARENT(i);
97 }
98}
99
100static void
101fixdown(T heap[], size_t i, size_t n)
102{
103 for ( ;; ) {
104 const size_t l = LEFT(i);
105 const size_t r = RIGHT(i);
106 size_t m = i;
107
108 if ( l < n && heap[l] < heap[m] ) {
109 m = l;
110 }
111
112 if ( r < n && heap[r] < heap[m] ) {
113 m = r;
114 }
115
116 if ( m == i ) {
117 break;
118 }
119
120 swap(heap, m, i);
121
122 i = m;
123 }
124}
125
126static bool
127is_heap(T heap[], size_t n)
128{
129 for ( size_t i = 0; i < n / 2; ++i ) {
130 const size_t l = LEFT(i);
131 const size_t r = RIGHT(i);
132
133 if ( l < n && heap[i] > heap[l] ) {
134 return false;
135 }
136 if ( r < n && heap[i] > heap[r] ) {
137 return false;
138 }
139 }
140 return true;
141}
142#endif
143
144static void
145heapify(T heap[], size_t n)
146{
147 for ( size_t i = n / 2; i-- > 0; ) {
148 fixdown(heap, i, n);
149 }
150
151 assert(is_heap(heap, n));
152}
153
154static void
155my_heapsort(T a[], size_t n)
156{
157 heapify(a, n);
158
159 while ( n-- ) {
160 swap(a, 0, n);
161 fixdown(a, 0, n);
162 }
163}
164
165// -------------------------------------------
166
167struct pq { // Priority Queue
168 T heap[251];
169 size_t sz;
170};
171
172void
173pq_init(struct pq *pq)
174{
175 pq->sz = 0;
176}
177
178bool
179pq_push(struct pq *pq, T data)
180{
181 if ( pq->sz == NELEM(pq->heap) ) {
182 return false;
183 }
184
185 pq->heap[pq->sz] = data;
186 fixup(pq->heap, pq->sz);
187 ++pq->sz;
188 return true;
189}
190
191bool
192pq_pop(struct pq *pq, T *data)
193{
194 if ( pq->sz == 0 ) {
195 return false;
196 }
197
198 *data = pq->heap[0];
199 --pq->sz;
200 pq->heap[0] = pq->heap[pq->sz];
201 fixdown(pq->heap, 0, pq->sz);
202 return true;
203}
204
205// -------------------------------------------
206
207void
208print_heap(T heap[], size_t n)
209{
210 if ( n ) {
211 printf("%d", heap[0]);
212 for ( size_t i = 1; i != n; ++i ) {
213 printf(", %d", heap[i]);
214 }
215 putchar('\n');
216 }
217}
218
219void
220test_heapsort(void)
221{
222 static const size_t N = 1000000;
223 T array[N];
224
225 puts("fülle....");
226 srand(time(NULL));
227 for ( size_t idx = 0; idx != NELEM(array); ++idx ) {
228 array[idx] = rand();
229 }
230
231 puts("sortiere....");
232 clock_t start = clock();
233 my_heapsort(array, NELEM(array));
234 clock_t end = clock();
235
236 puts("teste...");
237 for ( size_t idx = 1; idx != NELEM(array); ++idx ) {
238#if defined(MAX_HEAP)
239 if ( array[idx - 1] > array[idx] ) {
240 fprintf(stderr, "Fehler an Pos: %zu\n", idx);
241 exit(EXIT_FAILURE);
242 }
243#else
244 if ( array[idx - 1] < array[idx] ) {
245 fprintf(stderr, "Fehler an Pos: %zu\n", idx);
246 exit(EXIT_FAILURE);
247 }
248#endif
249 }
250 printf("ok! (%.3lf sec)\n", ((double) end - start) / CLOCKS_PER_SEC);
251}
252
253void
254test_pq(void)
255{
256 struct pq pq[1];
257
258 pq_init(pq);
259
260 for ( int i = 0; i != 10; ++i ) {
261 pq_push(pq, rand());
262 }
263
264 T data;
265 while ( pq_pop(pq, &data) ) {
266 printf("%d\n", data);
267 }
268}
269
270int
271main(void)
272{
273 test_heapsort();
274 test_pq();
275#if 1 // Heap-Testprogramm
276 // Beispiel aus "Informatik - Datenstrukturen und Konzepte der Abstraktion"
277 // Kapitel 5.10, Seite 372 ff.
278 T heap[20] = { 18, 18, 16, 9, 7, 1, 9, 3, 7, 5 };
279
280 //heapify(heap, 10);
281 assert(is_heap(heap, 10));
282 print_heap(heap, 10);
283
284 //heap[10] = 13; fixup(heap, 10);
285 swap(heap, 0, 9);
286 fixdown(heap, 0, 9);
287
288 assert(is_heap(heap, 9));
289 print_heap(heap, 9);
290#endif
291}