Added heap binomial adding.

master
Tomasz Polgrabia 2025-02-06 19:50:25 +01:00
parent 474953e5ec
commit 22c097789f
2 changed files with 348 additions and 0 deletions

View File

@ -0,0 +1,191 @@
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
typedef struct _node {
struct _node* right;
struct _node* child;
long lvl;
long key;
} node;
typedef struct _list {
node *node;
struct _list *next;
} list;
void visit_node_post_order(node *q, void (*callback)(node *)) {
if (!q) {
return;
}
visit_node_post_order(q->child, callback);
visit_node_post_order(q->right, callback);
callback(q);
}
void visit_node_pre_order(node *q, void (*callback)(node *)) {
if (!q) {
return;
}
callback(q);
visit_node_post_order(q->right, callback);
visit_node_post_order(q->child, callback);
}
void node_destroy(list *q) {
void (*func)(node *) = (void (*)(node *))free;
list *t = q;
while (t) {
visit_node_post_order(t->node, func);
t = t->next;
}
}
node* node_create(long key) {
node *res = (node *)malloc(sizeof(node));
res->lvl = 0;
res->key = key;
res->right = NULL;
res->child = NULL;
return res;
}
node* node_union_same_lvl(node* l, node* r) {
if (!l) {
return r;
}
if (!r) {
return l;
}
if (l->lvl != r->lvl) {
fprintf(stderr, "L lvl %d and R lvl %d do mismatch. Returning NULL\n", l->lvl, r->lvl);
return NULL;
}
node* item;
node* subitem;
if (l->key > r->key) {
// l main
item = l;
subitem = r;
} else {
// r main
item = r;
subitem = l;
}
if (item->child) {
node *t = item->child;
while (t->right != NULL) {
t = t->right;
}
t->right = subitem;
} else {
item->child = subitem;
}
item->lvl++; // we merged two same lvl binomial heap nodes and created on lvl bigger
return item;
}
void dump_node(node *q) {
printf("%d ", q->key);
}
void dump_heap(list *q) {
list *t = q;
while (t) {
printf("Binom lvl %d\n", t->node->lvl);
visit_node_pre_order(t->node, dump_node);
printf("\n");
t = t->next;
}
}
list* node_add(list *q, long key) {
list *c = NULL;
list *a = q;
node *b = node_create(key);
list *bl;
if (!q) {
a = (list*)malloc(sizeof(list));
a->node = b;
return a;
}
while (a) {
if (a->node->lvl > b->lvl) { // it a always will be bigger or equal
list *el = (list*)malloc(sizeof(list));
el->node = b;
el->next = a;
return el;
} else {
c = a->next;
a->node = node_union_same_lvl(a->node, b);
bl = a;
b = a->node;
a = c;
}
}
return bl;
}
int node_del(node *q) {
// TODO
return -1;
}
const int MAX_BUFFER = 0x1000;
int main() {
char cmd[MAX_BUFFER];
list *q = NULL;
while (1) {
fgets(cmd, MAX_BUFFER, stdin);
printf("Got command %s\n", cmd);
if (strlen(cmd) == 0 || cmd[0] == '\n') {
printf("Finished reading\n");
break;
} else if (memcmp(cmd, "ADD", 3) == 0) {
// handle command add
int x = atoi(cmd + 4);
q = node_add(q, x);
printf("Added number: %d\n", x);
} else if (memcmp(cmd, "DEL", 3) == 0) {
// handle command del
if (!q) {
fprintf(stderr, "There is nothing to delete - heap is empty\n");
continue;
}
// TODO: long key = node_del(q);
// printf("Removed element: %d\n", key);
} else {
// handle unknown command
fprintf(stderr, "Got unknown command %s\n", cmd);
}
dump_heap(q);
}
if (!q) {
node_destroy(q);
}
return 0;
}

View File

@ -0,0 +1,157 @@
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
typedef struct _node {
struct _node* left;
struct _node* right;
struct _node* child;
long lvl;
long key;
} node;
void visit_node_post_order(node *q, void (*callback)(node *)) {
if (!q) {
return;
}
visit_node_post_order(q->child, callback);
visit_node_post_order(q->right, callback);
callback(q);
}
void node_destroy(node *q) {
void (*func)(node *) = (void (*)(node *))free;
visit_node_post_order(q, func);
}
node* node_create(long key) {
node *res = (node *)malloc(sizeof(node));
res->lvl = 0;
res->key = key;
res->left = res;
res->right = res;
res->child = NULL;
return res;
}
node* node_union_same_lvl(node* l, node* r) {
if (!l) {
return r;
}
if (!r) {
return l;
}
if (l->lvl != r->lvl) {
fprintf(stderr, "L lvl %d and R lvl %d do mismatch. Returning NULL\n", l->lvl, r->lvl);
return NULL;
}
node* item;
node* subitem;
if (l->key > r->key) {
// l main
item = l;
subitem = r;
} else {
// r main
item = r;
subitem = l;
}
if (item->child) {
item->child->left->right = subitem; // we have two directional list (left,right links) where left of the beginning is the
// end and right of the end is the beginning
} else {
item->child = subitem;
}
item->lvl++; // we merged two same lvl binomial heap nodes and created on lvl bigger
return item;
}
node* node_add(node *q, long key) {
node *c = NULL;
node *a = q;
node *b = node_create(key);
if (q->lvl < 0) {
return b;
}
while (a) {
if (a->lvl > b->lvl) { // it a always will be bigger or equal
b->right = a;
a->left->right = b;
b->left = a->left; // a's ending
a->left = b;
return b;
} else {
b = node_union_same_lvl(a, b);
c = a->right;
a->right = NULL;
if (c == q) {
break;
}
a = c;
}
}
return b;
}
int node_del(node *q) {
// TODO
return -1;
}
const int MAX_BUFFER = 0x1000;
int main() {
char cmd[MAX_BUFFER];
node *q = (node *)malloc(sizeof(node));
q->lvl = -1;
q->key = 0xdeadbeaf; // it doesn't mother honestly
while (1) {
fgets(cmd, MAX_BUFFER, stdin);
printf("Got command %s\n", cmd);
if (strlen(cmd) == 0 || cmd[0] == '\n') {
printf("Finished reading\n");
break;
} else if (memcmp(cmd, "ADD", 3) == 0) {
// handle command add
int x = atoi(cmd + 4);
q = node_add(q, x);
printf("Added number: %d\n", x);
} else if (memcmp(cmd, "DEL", 3) == 0) {
// handle command del
if (!q) {
fprintf(stderr, "There is nothing to delete - heap is empty\n");
continue;
}
long key = node_del(q);
printf("Removed element: %d\n", key);
} else {
// handle unknown command
fprintf(stderr, "Got unknown command %s\n", cmd);
}
}
if (!q) {
node_destroy(q);
}
return 0;
}