forked from beanstalkd/beanstalkd
-
Notifications
You must be signed in to change notification settings - Fork 0
/
heap.c
112 lines (88 loc) · 1.82 KB
/
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
#include "dat.h"
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
static void
set(Heap *h, size_t k, void *x)
{
h->data[k] = x;
h->setpos(x, k);
}
static void
swap(Heap *h, size_t a, size_t b)
{
void *tmp;
tmp = h->data[a];
set(h, a, h->data[b]);
set(h, b, tmp);
}
static int
less(Heap *h, size_t a, size_t b)
{
return h->less(h->data[a], h->data[b]);
}
static void
siftdown(Heap *h, size_t k)
{
for (;;) {
size_t p = (k-1) / 2; /* parent */
if (k == 0 || less(h, p, k)) {
return;
}
swap(h, k, p);
k = p;
}
}
static void
siftup(Heap *h, size_t k)
{
for (;;) {
size_t l = k*2 + 1; /* left child */
size_t r = k*2 + 2; /* right child */
/* find the smallest of the three */
size_t s = k;
if (l < h->len && less(h, l, s)) s = l;
if (r < h->len && less(h, r, s)) s = r;
if (s == k) {
return; /* satisfies the heap property */
}
swap(h, k, s);
k = s;
}
}
// Heapinsert inserts x into heap h according to h->less.
// It returns 1 on success, otherwise 0.
int
heapinsert(Heap *h, void *x)
{
if (h->len == h->cap) {
void **ndata;
size_t ncap = (h->len+1) * 2; /* allocate twice what we need */
ndata = malloc(sizeof(void*) * ncap);
if (!ndata) {
return 0;
}
memcpy(ndata, h->data, sizeof(void*) * h->len);
free(h->data);
h->data = ndata;
h->cap = ncap;
}
size_t k = h->len;
h->len++;
set(h, k, x);
siftdown(h, k);
return 1;
}
void *
heapremove(Heap *h, size_t k)
{
if (k >= h->len) {
return 0;
}
void *x = h->data[k];
h->len--;
set(h, k, h->data[h->len]);
siftdown(h, k);
siftup(h, k);
return x;
}