-
Notifications
You must be signed in to change notification settings - Fork 9
/
heapq.c
88 lines (71 loc) · 1.95 KB
/
heapq.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
#include "heapq.h"
#include <string.h>
#include <assert.h>
static void
shiftdown(void *base, int i, int j, int len, int width, void *args,
int (*swap)(void *, void *, void *),
int (*compare)(const void *, const void *))
{
assert(i < len);
assert(j < len);
while (j > i) {
int k = (j - 1) / 2;
void *a = (char *)base + j * width;
void *b = (char *)base + k * width;
if (compare(a, b) < 0) {
swap(args, a, b);
} else {
break;
}
j = k;
}
}
static void
shiftup(int *base, int j, int len, int width, void *args,
int (*swap)(void *, void *, void *),
int (*compare)(const void *, const void *))
{
int i = j;
int k = j * 2 + 1;
int l = len - 1;
assert(j < len);
while (k < l) {
int r = k + 1;
if ((r < l) && (compare((char *)base + k * width,
(char *)base + r * width) >= 0))
{
k = r;
}
swap(args, (char *)base + j * width, (char *)base + k * width);
j = k;
k = j * 2 + 1;
}
shiftdown(base, i, j, len, width, args, swap, compare);
}
void
heapq_push(void *base, size_t nel, size_t width, void *item, void *args,
int (*swap)(void *, void *, void *),
int (*compare)(const void *, const void *))
{
memmove((char *)base + (nel - 1) * width, item, width);
shiftdown(base, 0, nel - 1, nel, width, args, swap, compare);
}
void
heapq_pop(void *base, size_t nel, size_t width, void *item, void *args,
int (*swap)(void *, void *, void *),
int (*compare)(const void *, const void *))
{
memmove(item, base, width);
memmove(base, (char *)base + (nel - 1) * width, width);
shiftup(base, 0, nel, width, args, swap, compare);
}
void
heapq_heapify(void *base, size_t nel, size_t width, void *args,
int (*swap)(void *, void *, void *),
int (*compare)(const void *, const void *))
{
int i;
for (i = nel / 2 - 1; i >= 0; i--) {
shiftup(base, i, nel, width, args, swap, compare);
}
}