Add small C program

This commit is contained in:
Paul Brinkmeier 2022-09-13 17:44:30 +02:00
parent 3309ca4a0c
commit ac9353cef3
2 changed files with 188 additions and 0 deletions

View File

@ -13,3 +13,9 @@ steps:
image: python image: python
commands: commands:
- python3 -c "print(6 * 7)" - python3 -c "print(6 * 7)"
- name: gcc
image: gcc
commands:
- cd pairingheap
- gcc -o pairingheap pairingheap.c
- ./pairingheap

182
algo2/pairingheap.c Normal file
View File

@ -0,0 +1,182 @@
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
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);
}