From 095ba92914a1483fef6bb6c579c69af3c3585021 Mon Sep 17 00:00:00 2001 From: david Date: Mon, 6 Oct 2025 17:45:39 -0500 Subject: [PATCH] Init commit, initial version of c heap-sort for generic types --- README.md | 4 +++ c/algorithms/sort_heap.c | 12 +++++++++ c/algorithms/sort_heap.h | 5 ++++ c/data_structures/heap.c | 54 ++++++++++++++++++++++++++++++++++++++++ c/data_structures/heap.h | 48 +++++++++++++++++++++++++++++++++++ c/test.c | 34 +++++++++++++++++++++++++ 6 files changed, 157 insertions(+) create mode 100644 README.md create mode 100644 c/algorithms/sort_heap.c create mode 100644 c/algorithms/sort_heap.h create mode 100644 c/data_structures/heap.c create mode 100644 c/data_structures/heap.h create mode 100644 c/test.c diff --git a/README.md b/README.md new file mode 100644 index 0000000..df77d66 --- /dev/null +++ b/README.md @@ -0,0 +1,4 @@ +# dlos (david's library of stuff) + +this repo is meant to contain any algorithms, data structures, utils, etc. which i +implement myself, whether for actual use or for learning purposes diff --git a/c/algorithms/sort_heap.c b/c/algorithms/sort_heap.c new file mode 100644 index 0000000..51acaf3 --- /dev/null +++ b/c/algorithms/sort_heap.c @@ -0,0 +1,12 @@ +#include "../data_structures/heap.h" +#include "sort_heap.h" + +void dlos_sort_heap(dlos_Heap *h) { + int original_size = h->size; + for (int i = h->size - 1; i > 0; i--) { + dlos_node_swap(h->arr, 0, i); + h->size -= 1; + dlos_sift_down(0, h); + } + h->size = original_size; +} diff --git a/c/algorithms/sort_heap.h b/c/algorithms/sort_heap.h new file mode 100644 index 0000000..776e7be --- /dev/null +++ b/c/algorithms/sort_heap.h @@ -0,0 +1,5 @@ +#pragma once + +#include "../data_structures/heap.h" + +void dlos_sort_heap(dlos_Heap *h); diff --git a/c/data_structures/heap.c b/c/data_structures/heap.c new file mode 100644 index 0000000..388133d --- /dev/null +++ b/c/data_structures/heap.c @@ -0,0 +1,54 @@ +#include "heap.h" + +// TODO: remove the extra checks for heap_size if i don't need them based on calling +static int parent(int i) { + return (i > 0) ? (i - 1) / 2 : -1; +} + +static int left_child(int i) { + return i * 2 + 1; +} + +static int right_child(int i) { + return i * 2 + 2; +} + +static int left_sibling(int i) { + return (i % 2 == 0) ? i - 1 : -1; +} + +static int right_sibling(int i) { + return (i % 2 == 1) ? i + 1 : -1; +} + +void dlos_node_swap(dlos_ComparableNode *arr, int a, int b) { + dlos_ComparableNode temp = arr[a]; + arr[a] = arr[b]; + arr[b] = temp; +} + +static int index_of_larger_child(int i, dlos_Heap *h) { + int larger = left_child(i); + if (larger >= h->size) { + return -1; + } + if (larger + 1 < h->size && h->compare(&h->arr[larger], &h->arr[larger + 1]) > 0) { + larger = larger + 1; + } + return larger; +} + +void dlos_sift_down(int i, dlos_Heap *h) { + int target = index_of_larger_child(i, h); + while (target > 0 && h->compare(&h->arr[i], &h->arr[target]) > 0) { + dlos_node_swap(h->arr, i, target); + i = target; + target = index_of_larger_child(i, h); + } +} + +void dlos_max_heap(dlos_Heap *h) { + for (int i = parent(h->size - 1); i >= 0; i--) { + dlos_sift_down(i, h); + } +} diff --git a/c/data_structures/heap.h b/c/data_structures/heap.h new file mode 100644 index 0000000..87dae53 --- /dev/null +++ b/c/data_structures/heap.h @@ -0,0 +1,48 @@ +#pragma once + +typedef struct dlos_ComparableNode { + void *value; +} dlos_ComparableNode; + +typedef struct dlos_Heap { + int size; + dlos_ComparableNode *arr; + int (*compare)(dlos_ComparableNode *a, dlos_ComparableNode *b); +} dlos_Heap; + +void dlos_node_swap(dlos_ComparableNode *arr, int a, int b); +void dlos_sift_down(int i, dlos_Heap *h); +void dlos_max_heap(dlos_Heap *h); + +// example of how the heap can be used +// here, each node value points to a plain int, but can substitute with other types +// +// int compare_nodes(dlos_ComparableNode *a, dlos_ComparableNode *b) { +// int left = *((int*) a->value); +// int right = *((int*) b->value); +// if (left > right) { +// return -1; +// } else if (left == right) { +// return 0; +// } else { +// return 1; +// } +// } +// +// int main(int argc, char *argv[]) { +// int test_size = 10; +// int data_storage[] = {73, 6, 57, 88, 60, 42, 83, 72, 48, 85}; +// dlos_ComparableNode a[test_size]; +// for (int i = 0; i < test_size; i++) { +// a[i].value = &data_storage[i]; +// } +// dlos_Heap heap = { .size = test_size, .arr = a, .compare = compare_nodes }; +// dlos_max_heap(&heap); +// dlos_sort_heap(&heap); +// for (int i = 0; i < test_size; i++) { +// if (i == 0) printf("sorted: "); +// printf("%d, ", *((int*) heap.arr[i].value)); +// if (i == test_size - 1) printf("\n"); +// } +// return 0; +// } diff --git a/c/test.c b/c/test.c new file mode 100644 index 0000000..e3ef258 --- /dev/null +++ b/c/test.c @@ -0,0 +1,34 @@ +#include + +#include "data_structures/heap.h" +#include "algorithms/sort_heap.h" + +int compare_nodes(dlos_ComparableNode *a, dlos_ComparableNode *b) { + int left = *((int*) a->value); + int right = *((int*) b->value); + if (left > right) { + return -1; + } else if (left == right) { + return 0; + } else { + return 1; + } +} + +int main(int argc, char *argv[]) { + int test_size = 10; + int data_storage[] = {73, 6, 57, 88, 60, 42, 83, 72, 48, 85}; + dlos_ComparableNode a[test_size]; + for (int i = 0; i < test_size; i++) { + a[i].value = &data_storage[i]; + } + dlos_Heap heap = { .size = test_size, .arr = a, .compare = compare_nodes }; + dlos_max_heap(&heap); + dlos_sort_heap(&heap); + for (int i = 0; i < test_size; i++) { + if (i == 0) printf("sorted: "); + printf("%d, ", *((int*) heap.arr[i].value)); + if (i == test_size - 1) printf("\n"); + } + return 0; +}