/
min_heap.c
161 lines (139 loc) · 2.75 KB
/
min_heap.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
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
#include <stdlib.h>
#include <stdbool.h>
#include <limits.h>
#include "debug.h"
#include "min_heap.h"
/* - - - - - - - - - - - - - - - - - - - - */
typedef struct {
unsigned long key;
void *value;
} node;
struct min_heap {
int size;
int avail;
node *nodes;
};
/* - - - - - - - - - - - - - - - - - - - - */
static inline int parent(int i);
static inline int left(int i);
static inline int right(int i);
static inline void exchange(node *nodes, int a, int b);
static void min_heapify(min_heap_t h, int i);
static void min_heap_resize(min_heap_t h);
static void min_heap_grow(min_heap_t h);
static void min_heap_shrink(min_heap_t h);
/* - - - - - - - - - - - - - - - - - - - - */
min_heap_t
min_heap_new(void)
{
min_heap_t h = malloc(sizeof(*h));
if (h) {
h->size = 0;
h->avail = 0;
h->nodes = NULL;
}
return h;
}
bool
min_heap_is_empty(min_heap_t h)
{
return h->size == 0;
}
int
min_heap_size(min_heap_t h)
{
return h->size;
}
void
min_heap_add(min_heap_t h, unsigned long k, void *v)
{
if (h->size + 1 > h->avail) {
min_heap_grow(h);
}
node *n = &h->nodes[h->size];
n->key = INT_MAX;
n->value = v;
min_heap_decrease_key(h, h->size, k);
h->size++;
}
void *
min_heap_peek(min_heap_t h)
{
return h->nodes[0].value;
}
unsigned long
min_heap_peek_key(min_heap_t h)
{
return h->nodes[0].key;
}
void *
min_heap_remove(min_heap_t h)
{
void *v = h->nodes[0].value;
h->size--;
h->nodes[0] = h->nodes[h->size];
if (h->size < h->avail/2) {
min_heap_shrink(h);
}
min_heapify(h, 0);
return v;
}
void
min_heap_decrease_key(min_heap_t h, int i, unsigned long key)
{
node *nodes = h->nodes;
nodes[i].key = key;
while (i > 0 && nodes[parent(i)].key > nodes[i].key) {
exchange(nodes, i, parent(i));
i = parent(i);
}
}
void
min_heap_free(min_heap_t h)
{
if (h->nodes) {
free(h->nodes);
}
free(h);
}
static inline int parent(int i) { return i>>1; }
static inline int left(int i) { return i<<1; }
static inline int right(int i) { return left(i)+1; }
static inline void
exchange(node *nodes, int a, int b)
{
node t = nodes[a];
nodes[a] = nodes[b];
nodes[b] = t;
}
static void
min_heapify(min_heap_t h, int i)
{
node *nodes = h->nodes;
int l = left(i);
int r = right(i);
int min = i;
if (l <= h->size && nodes[l].key < nodes[min].key) { min = l; }
if (r <= h->size && nodes[r].key < nodes[min].key) { min = r; }
if (min != i) {
exchange(nodes, i, min);
min_heapify(h, min);
}
}
static void
min_heap_resize(min_heap_t h)
{
h->nodes = realloc(h->nodes, sizeof(node)*h->avail);
}
static void
min_heap_grow(min_heap_t h)
{
h->avail = h->avail == 0 ? 1 : h->avail*2;
min_heap_resize(h);
}
static void
min_heap_shrink(min_heap_t h)
{
h->avail /= 2;
min_heap_resize(h);
}