-
Notifications
You must be signed in to change notification settings - Fork 0
/
dlb_heap.h
146 lines (123 loc) · 3.45 KB
/
dlb_heap.h
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
#ifndef DLB_HEAP_H
#define DLB_HEAP_H
//------------------------------------------------------------------------------
// Copyright 2018 Dan Bechard
//------------------------------------------------------------------------------
//-- header --------------------------------------------------------------------
#include "dlb_vector.h"
//typedef int (*dlb_heap_comparer)(void *a, void *b);
typedef struct dlb_heap_node {
u32 priority;
void *data;
} dlb_heap_node;
typedef struct dlb_heap {
// Note: nodes[0] is reserved to make index arithmetic cleaner
dlb_heap_node *nodes;
} dlb_heap;
#endif
//-- end of header -------------------------------------------------------------
#ifdef __INTELLISENSE__
/* This makes MSVC intellisense work. */
#define DLB_HEAP_IMPLEMENTATION
#endif
//-- implementation ------------------------------------------------------------
#ifdef DLB_HEAP_IMPLEMENTATION
#ifndef DLB_HEAP_IMPL_INTERNAL
#define DLB_HEAP_IMPL_INTERNAL
void dlb_heap_init(dlb_heap *heap)
{
dlb_vec_push(heap->nodes, (dlb_heap_node){ 0, 0 });
}
void dlb_heap_free(dlb_heap *heap)
{
dlb_vec_free(heap->nodes);
}
size_t dlb_heap_size(dlb_heap *heap)
{
size_t len = dlb_vec_len(heap->nodes);
return len - 1;
}
bool dlb_heap_empty(dlb_heap *heap)
{
size_t size = dlb_heap_size(heap);
return size == 0;
}
void dlb_heap__swap_nodes(dlb_heap *heap, size_t a, size_t b)
{
dlb_heap_node c = heap->nodes[a];
heap->nodes[a] = heap->nodes[b];
heap->nodes[b] = c;
}
#define dlb_heap__parent(index) ((index) / 2)
static size_t dlb_heap__left(dlb_heap *heap, size_t size, size_t index)
{
size_t left = index * 2;
return left < size ? left : 0;
}
static size_t dlb_heap__right(dlb_heap *heap, size_t size, size_t index)
{
size_t right = index * 2 + 1;
return right < size ? right : 0;
}
void dlb_heap__sift_up(dlb_heap *heap, size_t index)
{
size_t parent = dlb_heap__parent(index);
while (parent && heap->nodes[index].priority > heap->nodes[parent].priority)
{
dlb_heap__swap_nodes(heap, index, parent);
index = parent;
parent = dlb_heap__parent(index);
}
}
void dlb_heap__sift_down(dlb_heap *heap, size_t index)
{
size_t size = dlb_heap_size(heap);
for (;;)
{
size_t left = dlb_heap__left(heap, size, index);
size_t right = dlb_heap__right(heap, size, index);
size_t swap = (heap->nodes[left].priority >= heap->nodes[right].priority)
? left : right;
if (heap->nodes[index].priority >= heap->nodes[swap].priority)
break;
dlb_heap__swap_nodes(heap, index, swap);
index = swap;
}
}
void dlb_heap_push(dlb_heap *heap, u32 priority, void *data)
{
DLB_ASSERT(priority > 0);
dlb_vec_push(heap->nodes, (dlb_heap_node){ priority, data });
dlb_heap__sift_up(heap, dlb_vec_len(heap->nodes) - 1);
}
void *dlb_heap_peek(dlb_heap *heap)
{
if (dlb_heap_empty(heap))
{
return NULL;
}
void *data = heap->nodes[1].data;
return data;
}
void *dlb_heap_pop(dlb_heap *heap)
{
size_t last = dlb_heap_size(heap);
if (!last)
{
return NULL;
}
void *data = heap->nodes[1].data;
if (last >= 1)
{
if (last > 1)
{
heap->nodes[1] = heap->nodes[last];
dlb_heap__sift_down(heap, 1);
}
dlb_vec_pop(heap->nodes);
}
return data;
}
#endif
#endif
//-- end of implementation -----------------------------------------------------