-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathpqueue.h
107 lines (92 loc) · 2.53 KB
/
pqueue.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
#ifndef PQUEUE_H
#define PQUEUE_H
#include "common.h"
#include "dynarr.h"
#define GET_PARENT(i) (((i) - 1) / 2)
#define GET_LEFT_CHILD(i) ((2 * (i)) + 1)
#define GET_RIGHT_CHILD(i) ((2 * (i)) + 2)
typedef struct PriorityQueue {
DynArr *heap;
} PriorityQueue;
typedef struct PriorityNode {
void *data;
f32 priority;
} PriorityNode;
PriorityQueue *pq_init() {
PriorityQueue *pq = malloc(sizeof(PriorityQueue));
pq->heap = da_init();
return pq;
}
PriorityNode *pnode_init(void *data, f32 priority) {
PriorityNode *pnode = (PriorityNode *)malloc(sizeof(PriorityNode));
pnode->data = data;
pnode->priority = priority;
return pnode;
}
void sift_up_conn_heap(DynArr *heap, u64 idx) {
if (idx != 0) {
u64 parent_idx = GET_PARENT(idx);
f32 parent_priority = ((PriorityNode *)heap->buffer[parent_idx])->priority;
f32 idx_priority = ((PriorityNode *)heap->buffer[idx])->priority;
if (parent_priority > idx_priority) {
PriorityNode *tmp = (PriorityNode *)heap->buffer[parent_idx];
heap->buffer[parent_idx] = heap->buffer[idx];
heap->buffer[idx] = tmp;
sift_up_conn_heap(heap, parent_idx);
}
}
}
void sift_down_conn_heap(DynArr *heap, u64 idx) {
u64 left_child_idx = GET_LEFT_CHILD(idx);
u64 right_child_idx = GET_RIGHT_CHILD(idx);
u64 min_idx;
if (right_child_idx >= heap->size) {
if (left_child_idx >= heap->size) {
return;
} else {
min_idx = left_child_idx;
}
} else {
PriorityNode *left = heap->buffer[left_child_idx];
PriorityNode *right = heap->buffer[left_child_idx];
if (left->priority <= right->priority) {
min_idx = left_child_idx;
} else {
min_idx = right_child_idx;
}
}
PriorityNode *cur = heap->buffer[idx];
PriorityNode *min = heap->buffer[min_idx];
if (cur->priority > min->priority) {
PriorityNode *tmp = min;
heap->buffer[min_idx] = heap->buffer[idx];
heap->buffer[idx] = tmp;
sift_down_conn_heap(heap, min_idx);
}
}
void pq_push(PriorityQueue *pq, void *data, f32 priority) {
PriorityNode *pn = pnode_init(data, priority);
da_insert(pq->heap, pn);
u64 inserted_idx = pq->heap->size - 1;
sift_up_conn_heap(pq->heap, inserted_idx);
}
void *pq_pop(PriorityQueue *pq) {
if (pq->heap->size == 0) {
printf("Heap is empty!\n");
return NULL;
} else {
void *ret = ((PriorityNode *)pq->heap->buffer[0])->data;
free(pq->heap->buffer[0]);
pq->heap->buffer[0] = pq->heap->buffer[pq->heap->size - 1];
pq->heap->size--;
if (pq->heap->size > 0) {
sift_down_conn_heap(pq->heap, 0);
}
return ret;
}
}
void pq_free(PriorityQueue *pq) {
da_free_data(pq->heap);
free(pq);
}
#endif