Implement min heap
This commit is contained in:
parent
730ec80220
commit
6b52d4d9cd
@ -2,6 +2,7 @@ add_library(lib
|
||||
construct.c
|
||||
desugar.c
|
||||
fsa.c
|
||||
min_heap.c
|
||||
parse.c
|
||||
regex.c
|
||||
)
|
||||
|
12
lib/include/min_heap.h
Normal file
12
lib/include/min_heap.h
Normal 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
53
lib/min_heap.c
Normal 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;
|
||||
}
|
@ -20,5 +20,6 @@ add_test_suites(
|
||||
construct_tests.c
|
||||
desugar_tests.c
|
||||
fsa_tests.c
|
||||
min_heap_tests.c
|
||||
parse_tests.c
|
||||
)
|
||||
|
49
tests/min_heap_tests.c
Normal file
49
tests/min_heap_tests.c
Normal 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();
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user