算法导论代码 第20章 斐波那契堆

来源:互联网 发布:家具画图软件 编辑:程序博客网 时间:2024/05/01 10:26

20章 斐波那契堆

#include <stdio.h>#include <limits.h>#include <string.h>#include <stdbool.h>#include <math.h>#include <stdlib.h>typedef struct fib_heap *heap;struct heap_node {void *key;int degree;bool mark;struct heap_node *child;struct heap_node *left;struct heap_node *right;struct heap_node *parent;};struct fib_heap {int (*comp) (const void *, const void *);struct heap_node *min;int num;};void heap_node_ini(struct heap_node *x, void *key){x->key = key;x->degree = 0;x->mark = false;x->parent = NULL;x->child = NULL;x->left = x;x->right = x;}void swap(void *a, void *b, size_t elem_size){if (a == NULL || b == NULL || a == b)return;char temp[elem_size];/*变长数组 */memcpy(temp, a, elem_size);memcpy(a, b, elem_size);memcpy(b, temp, elem_size);}heap heap_create(int (*comp) (const void *, const void *)){heap h = malloc(sizeof(struct fib_heap));h->comp = comp;h->num = 0;h->min = NULL;return h;}//删除结点,如果只有x一个结点的话,这个函数无效void list_delete(struct heap_node **pos, struct heap_node *x){if (x->right == x)//只有一个结点{*pos = NULL;return;}x->left->right = x->right;x->right->left = x->left;if (*pos == x) {*pos = x->right;}}//插入结点x到pos的左边,如果pos为空,pos=xvoid list_insert(struct heap_node **pos, struct heap_node *x){if (*pos == NULL) {*pos = x;x->left = x;x->right = x;} else {x->left = (*pos)->left;(*pos)->left->right = x;x->right = (*pos);(*pos)->left = x;}}void add_root(heap h, struct heap_node *x){list_insert(&h->min, x);x->parent = NULL;x->mark = false;if (h->comp(x->key, h->min->key) < 0) {h->min = x;}}//下面的过程将结点x插入斐波那契堆中,假定结点x已被分配,且key[x]也已填有内容void heap_insert(heap h, struct heap_node *x){x->degree = 0;x->parent = NULL;x->child = NULL;x->left = x;x->right = x;add_root(h, x);++h->num;}//最小结点struct heap_node *heap_minimum(heap h){return h->min;}void heap_destroy(heap h);//将另一个斐波那契堆合并到当前堆,另一堆合并到当前最小结点的右边void heap_union(heap ha, heap hb){if (hb == NULL || hb->min == NULL) {return;}if (ha->min == NULL) {ha->min = hb->min;} else {//最小结点的右边结点struct heap_node *ha_min_right = ha->min->right;ha->min->right = hb->min;//另一个堆最小结点的左结点,即最后一个结点struct heap_node *hb_min_left = hb->min->left;hb->min->left = ha->min;hb_min_left->right = ha_min_right;ha_min_right->left = hb_min_left;}if (ha->min == NULL    || (hb->min != NULL && ha->comp(hb->min->key, ha->min->key) < 0)) {ha->min = hb->min;}ha->num += hb->num;hb->min = NULL;heap_destroy(hb);}void link(heap h, struct heap_node *y, struct heap_node *x){list_delete(&h->min, y);list_insert(&x->child, y);y->parent = x;y->mark = false;++x->degree;}//合并根表void consolidate(heap h){if (h->min == NULL)return;int D = floor(log(h->num) / log(1.618));//计算D值struct heap_node *A[D];for (int i = 0; i < D; i++) {A[i] = NULL;}struct heap_node *x = NULL;struct heap_node *y = NULL;int d;struct heap_node *w = h->min;struct heap_node *end = h->min->left;bool loop_flag = true;while (loop_flag) {x = w;if (w != end) {w = w->right;} else {loop_flag = false;//w到达最后一个结点,循环结束}d = x->degree;while (A[d] != NULL) {y = A[d];if (h->comp(x->key, y->key) > 0) {swap(&x, &y, sizeof(struct heap_node *));}link(h, y, x);A[d] = NULL;++d;}A[d] = x;}h->min = NULL;for (int i = 0; i < D; ++i) {if (A[i] != NULL) {add_root(h, A[i]);}}}//抽取具有最小关键字的结点,并返回一个指向该结点的指针struct heap_node *heap_extract_min(heap h){struct heap_node *z = h->min;if (z == NULL)return NULL;struct heap_node *x = NULL;while (z->degree > 0) {x = z->child;if (x->right == x) {z->child = NULL;} else {z->child = z->child->right;}list_delete(&z->child, x);add_root(h, x);--z->degree;}if (z == z->right) {list_delete(&h->min, z);} else {list_delete(&h->min, z);consolidate(h);}--h->num;return z;}void cut(heap h, struct heap_node *x, struct heap_node *y){list_delete(&y->child, x);add_root(h, x);--y->degree;}void cascading_cut(heap h, struct heap_node *y){struct heap_node *z = y->parent;if (z == NULL)return;if (y->mark == false) {y->mark = true;} else {cut(h, y, z);cascading_cut(h, z);}}//将斐波那契堆中的某一结点x的关键字减少为一个新值kvoid heap_decrease_key(heap h, struct heap_node *x){struct heap_node *y = x->parent;if (y != NULL && h->comp(x->key, y->key) < 0) {cut(h, x, y);cascading_cut(h, y);}if (h->comp(x->key, h->min->key) < 0) {h->min = x;}}bool heap_is_empty(heap h){return h->min == NULL;}void heap_destroy(heap h){while (!heap_is_empty(h)) {struct heap_node *x = heap_extract_min(h);free(x->key);free(x);}free(h);}void heap_display(heap h, void (*print_key) (const void *)){if (h->min == NULL)return;struct heap_node *x = h->min;bool loop_flag = true;struct heap_node *end = h->min->left;while (loop_flag) {print_key(x->key);printf(" ");if (x != end) {x = x->right;} else {loop_flag = false;}}printf("\n");}int cmp_int(const void *p1, const void *p2){const int *pa = p1;const int *pb = p2;if (*pa < *pb)return -1;if (*pa == *pb)return 0;return 1;}void print_key(const void *key){const int *p = key;printf("%d", *p);}int main(){heap h = heap_create(cmp_int);struct heap_node *x = NULL;struct heap_node *parray[10];for (int i = 0; i < 10; i++) {struct heap_node *x = malloc(sizeof(struct heap_node));int *ip = malloc(sizeof(int));*ip = i;heap_node_ini(x, ip);heap_insert(h, x);parray[i] = x;}printf("原始数据:\n");heap_display(h, print_key);int change_index = 5;*(int*)parray[change_index]->key=INT_MIN;heap_decrease_key(h, parray[change_index]);printf("修改了第%d个结点的数据:\n", change_index);heap_display(h, print_key);heap hb = heap_create(cmp_int);for (int i = 10; i < 20; i++) {struct heap_node *x = malloc(sizeof(struct heap_node));int *ip = malloc(sizeof(int));*ip = i;heap_node_ini(x, ip);heap_insert(hb, x);}heap_union(h, hb);printf("合并了之后的数据:\n");heap_display(h, print_key);printf("按从小到大的顺序输出:\n");while (!heap_is_empty(h)) {x = heap_extract_min(h);print_key(x->key);printf(" ");free(x->key);free(x);}printf("\n");heap_destroy(h);return 0;}


原创粉丝点击