From ac9353cef36e3a994e51d50cc53fc672093c26a9 Mon Sep 17 00:00:00 2001 From: Paul Brinkmeier Date: Tue, 13 Sep 2022 17:44:30 +0200 Subject: [PATCH] Add small C program --- .drone.yml | 6 ++ algo2/pairingheap.c | 182 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 188 insertions(+) create mode 100644 algo2/pairingheap.c diff --git a/.drone.yml b/.drone.yml index 5ff0e22..c43890d 100644 --- a/.drone.yml +++ b/.drone.yml @@ -13,3 +13,9 @@ steps: image: python commands: - python3 -c "print(6 * 7)" + - name: gcc + image: gcc + commands: + - cd pairingheap + - gcc -o pairingheap pairingheap.c + - ./pairingheap diff --git a/algo2/pairingheap.c b/algo2/pairingheap.c new file mode 100644 index 0000000..e2624a5 --- /dev/null +++ b/algo2/pairingheap.c @@ -0,0 +1,182 @@ +#include +#include +#include + +struct PHeapNode { + int key; + struct PHeapNode *parent; + struct PHeapNode *left; + struct PHeapNode *right; + struct PHeapNode *children; +}; + +void phn_init(struct PHeapNode *phn, int key) { + phn->key = key; + phn->parent = NULL; + phn->left = NULL; + phn->right = NULL; + phn->children = NULL; +} + +static void phn_list_insert(struct PHeapNode **phn, struct PHeapNode *h) { + if (*phn == NULL) { + // list empty ==> h is only element now + h->left = h; + h->right = h; + *phn = h; + } else { + // list not empty ==> insert at the end + (*phn)->left->right = h; + h->left = (*phn)->left; + h->right = *phn; + (*phn)->left = h; + } +} + +static void phn_list_remove(struct PHeapNode **phn, struct PHeapNode *h) { + assert(*phn != NULL); + + if (h->left == h) { + assert(h->right == h); + // empty list + *phn = NULL; + } else { + // rearrange pointers + struct PHeapNode *tmp = h->left; + h->left->right = h->right; + h->right->left = tmp; + + if (*phn == h) { + *phn = h->left; + } + } + + h->parent = NULL; + h->left = NULL; + h->right = NULL; +} + +// returns a or b +struct PHeapNode *phn_union(struct PHeapNode *a, struct PHeapNode *b) { + struct PHeapNode *min = a->key < b->key ? a : b; + struct PHeapNode *max = a->key < b->key ? b : a; + + phn_list_insert(&min->children, max); + return min; +} + +struct PHeap { + struct PHeapNode *roots; + struct PHeapNode *min; +}; + +void ph_init(struct PHeap *ph) { + ph->roots = NULL; + ph->min = NULL; +} + +void ph_print(struct PHeap *ph) { + printf("roots: "); + if (ph->roots != NULL) { + struct PHeapNode *first = ph->roots; + struct PHeapNode *curr = first; + do { + printf("--{%d}", curr->key); + if (ph->min == curr) { + printf("'"); + } + curr = curr->right; + } while (curr != first); + } + printf("--\n"); +} + +void ph_newtree(struct PHeap *ph, struct PHeapNode *h) { + assert(h->parent == NULL); + + phn_list_insert(&ph->roots, h); + if (ph->min == NULL || h->key < ph->min->key) { + ph->min = h; + } +} + +void ph_insert_malloc(struct PHeap *ph, int key) { + struct PHeapNode *h = malloc(sizeof(struct PHeapNode)); + phn_init(h, key); + ph_newtree(ph, h); +} + +struct PHeapNode *ph_deletemin(struct PHeap *ph) { + if (ph->min == NULL) { + return NULL; + } + + struct PHeapNode *m = ph->min; + + // forest := forest \ {m} + phn_list_remove(&ph->roots, m); + ph->min = NULL; + + // foreach child h of m do newTree(h) + while (m->children != NULL) { + struct PHeapNode *curr = m->children; + phn_list_remove(&m->children, m->children); + ph_newtree(ph, curr); + } + + // perform pair-wise union operations on the roots in forest + // update minPtr + if (ph->roots != NULL) { + struct PHeapNode *new_roots = NULL; + + while (ph->roots != NULL && ph->roots->right != ph->roots) { + // while two elements are available: + struct PHeapNode *a = ph->roots; + struct PHeapNode *b = ph->roots->right; + phn_list_remove(&ph->roots, a); + phn_list_remove(&ph->roots, b); + + a = phn_union(a, b); + phn_list_insert(&new_roots, a); + if (ph->min == NULL || a->key < ph->min->key) { + ph->min = a; + } + } + + if (ph->roots != NULL) { + // another element remains + struct PHeapNode *last = ph->roots; + phn_list_remove(&ph->roots, last); + phn_list_insert(&new_roots, last); + if (ph->min == NULL || last->key < ph->min->key) { + ph->min = last; + } + } + + assert(ph->roots == NULL); + ph->roots = new_roots; + } + + return m; +} + +int main() { + struct PHeap ph; + ph_init(&ph); + + ph_insert_malloc(&ph, 42); + ph_insert_malloc(&ph, 10); + ph_insert_malloc(&ph, 0); + ph_insert_malloc(&ph, 100); + ph_insert_malloc(&ph, 12); + + ph_print(&ph); + + while (ph.min != NULL) { + struct PHeapNode *h = ph_deletemin(&ph); + printf("deleteMin: %d\n", h->key); + free(h); + } + + ph_print(&ph); +}