Implement min heap

This commit is contained in:
Camden Dixie O'Brien 2024-10-29 16:02:59 +00:00
parent 730ec80220
commit 6b52d4d9cd
5 changed files with 116 additions and 0 deletions

View File

@ -2,6 +2,7 @@ add_library(lib
construct.c construct.c
desugar.c desugar.c
fsa.c fsa.c
min_heap.c
parse.c parse.c
regex.c regex.c
) )

12
lib/include/min_heap.h Normal file
View File

@ -0,0 +1,12 @@
/*
* Copyright (c) Camden Dixie O'Brien
* SPDX-License-Identifier: AGPL-3.0-only
*/
#ifndef MIN_HEAP_H
#define MIN_HEAP_H
void min_heap_heapify(int *xs, int count);
int min_heap_pop(int *xs, int *count);
#endif

53
lib/min_heap.c Normal file
View File

@ -0,0 +1,53 @@
/*
* Copyright (c) Camden Dixie O'Brien
* SPDX-License-Identifier: AGPL-3.0-only
*/
#include "min_heap.h"
static inline int left(int i)
{
return 2 * i + 1;
}
static inline int parent(int i)
{
return (i - 1) / 2;
}
static inline void swap(int *xs, int a, int b)
{
int tmp = xs[a];
xs[a] = xs[b];
xs[b] = tmp;
}
static void sift_down(int *xs, int root, int count)
{
int child;
while ((child = left(root)) < count) {
if (child + 1 < count && xs[child] > xs[child + 1])
++child;
if (xs[root] > xs[child]) {
swap(xs, root, child);
root = child;
} else {
return;
}
}
}
void min_heap_heapify(int *xs, int count)
{
for (int i = parent(count - 1); i >= 0; --i)
sift_down(xs, i, count);
}
int min_heap_pop(int *xs, int *count)
{
int min = xs[0];
--(*count);
xs[0] = xs[*count];
sift_down(xs, 0, *count);
return min;
}

View File

@ -20,5 +20,6 @@ add_test_suites(
construct_tests.c construct_tests.c
desugar_tests.c desugar_tests.c
fsa_tests.c fsa_tests.c
min_heap_tests.c
parse_tests.c parse_tests.c
) )

49
tests/min_heap_tests.c Normal file
View File

@ -0,0 +1,49 @@
/*
* Copyright (c) Camden Dixie O'Brien
* SPDX-License-Identifier: AGPL-3.0-only
*/
#include "min_heap.h"
#include "testing.h"
#include <stdbool.h>
static bool is_min_heap(int *xs, int count)
{
for (int i = 0; i < count; ++i) {
const int left = 2 * i + 1;
const int right = 2 * i + 2;
if (left < count && xs[left] < xs[i])
return false;
if (right < count && xs[right] < xs[i])
return false;
}
return true;
}
static void array_is_min_heap_after_heapify(void)
{
int xs[] = { 54, 12, 35, 43, 21, 12, 34, 52, 34, 23 };
const int len = sizeof(xs) / sizeof(int);
min_heap_heapify(xs, len);
ASSERT_TRUE(is_min_heap(xs, len));
}
static void extract_root_yields_min(void)
{
int xs[] = { 71, 31, 12, 21, 65, 53, 54, 10 };
int len = 8;
min_heap_heapify(xs, len);
ASSERT_EQ(10, min_heap_pop(xs, &len));
ASSERT_EQ(12, min_heap_pop(xs, &len));
ASSERT_EQ(21, min_heap_pop(xs, &len));
ASSERT_EQ(5, len);
}
int main(void)
{
TESTING_BEGIN();
array_is_min_heap_after_heapify();
extract_root_yields_min();
return TESTING_END();
}