算法导论代码 第19章 二项堆

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

19章 二项堆

#include <stdio.h>#include <limits.h>#include <string.h>#include <stdbool.h>#include <stdlib.h>typedef struct binomial_heap *heap;struct heap_node {void *key;int degree;struct heap_node *child;struct heap_node *sibling;struct heap_node *parent;};struct binomial_heap {int (*comp) (const void *, const void *);//这个函数是用于结点交换时通知调用void (*on_swap) (struct heap_node *, struct heap_node *);struct heap_node *head;};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);}void heap_node_ini(struct heap_node *x, void *key){x->key = key;x->degree = 0;x->parent = NULL;x->child = NULL;x->sibling = NULL;}heap heap_create(int (*comp) (const void *, const void *), void (*on_swap) (struct heap_node *, struct heap_node *)){heap h = malloc(sizeof(struct binomial_heap));h->comp = comp;h->on_swap = on_swap;h->head = NULL;return h;}//返回一个指针,它指向包含n个结点的二项堆H中具有最小关键字的结点struct heap_node *heap_minimum(heap h){struct heap_node *y = NULL;struct heap_node *x = h->head;void *min;bool first = true;while (x != NULL) {if (first || h->comp(x->key, min) < 0) {first = false;min = x->key;y = x;}x = x->sibling;}return y;}bool heap_is_empty(heap h){return h->head == NULL;}//将结点y为根和z为根的树连接过来,使z成为y的父结点void link(struct heap_node *y, struct heap_node *z){y->parent = z;y->sibling = z->child;z->child = y;z->degree = z->degree + 1;}void heap_destroy(heap h);//将ha和hb合并成一个按度数的单调递增次序排列的链表struct heap_node *heap_merge(heap ha, heap hb){struct heap_node *pa = ha->head;struct heap_node *pb = hb->head;struct heap_node *head = NULL;struct heap_node *tail = NULL;while (pa != NULL && pb != NULL) {if (pa->degree <= pb->degree) {if (head == NULL) {head = pa;tail = pa;pa = pa->sibling;tail->sibling = NULL;} else {tail->sibling = pa;pa = pa->sibling;tail = tail->sibling;tail->sibling = NULL;}} else {if (head == NULL) {head = pb;tail = pb;pb = pb->sibling;tail->sibling = NULL;} else {tail->sibling = pb;pb = pb->sibling;tail = tail->sibling;tail->sibling = NULL;}}}if (pa != NULL && pb == NULL) {if (head == NULL) {head = pa;tail = pa;} else {tail->sibling = pa;}}if (pa == NULL && pb != NULL) {if (head == NULL) {head = pb;tail = pb;} else {tail->sibling = pb;}}hb->head = NULL;heap_destroy(hb);return head;}//将hb合并到ha中void heap_union(heap ha, heap hb){//将ha和hb的根表合并成一个按度数的单调递增次序排列的链表ha->head = heap_merge(ha, hb);if (ha->head == NULL) {return;}struct heap_node *prev = NULL;struct heap_node *x = ha->head;struct heap_node *next = x->sibling;while (next != NULL) {//情况1:x->degree!=next->degree//情况2:x->degree==next->degree==next->sibling->degreeif ((x->degree != next->degree) ||    (next->sibling != NULL     && next->sibling->degree == x->degree)) {prev = x;x = next;} else if (ha->comp(x->key, next->key) <= 0) {//情况3:x->degree==next->degree!=next->sibling->degree,x->key<=next->keyx->sibling = next->sibling;link(next, x);} else {//情况4:x->degree==next->degree!=next->sibling->degree,next->key<=x->keyif (prev == NULL) {ha->head = next;} else {prev->sibling = next;}link(x, next);x = next;}next = x->sibling;}}//反转x的孩子,随便把x的孩子的父结点置为空void reverse_children(struct heap_node *x){if (x == NULL || x->child == NULL)return;struct heap_node *prev = x->child;struct heap_node *current = prev->sibling;struct heap_node *next = NULL;while (current != NULL) {next = current->sibling;current->sibling = prev;current->parent = NULL;prev = current;current = next;}x->child->sibling = NULL;x->child->parent = NULL;x->child = prev;}//下面的过程将结点x插入二项堆中,假定结点x已被分配,且key[x]也已填有内容void heap_insert(heap h, struct heap_node *x){heap hb = heap_create(h->comp, h->on_swap);hb->head = x;heap_union(h, hb);}struct heap_node *heap_remove_minimum(heap h){struct heap_node *x = h->head;if (x == NULL)return NULL;struct heap_node *prev = NULL;struct heap_node *min_prev = NULL;void *min;bool first = true;while (x != NULL) {if (first || h->comp(x->key, min) < 0) {first = false;min = x->key;min_prev = prev;}prev = x;x = x->sibling;}//删除结点xif (min_prev == NULL) {x = h->head;h->head = x->sibling;} else {x = min_prev->sibling;min_prev->sibling = x->sibling;}return x;}//抽取具有最小关键字的结点,并返回一个指向该结点的指针struct heap_node *heap_extract_min(heap h){struct heap_node *x = heap_remove_minimum(h);if (x == NULL)return NULL;reverse_children(x);heap hb = heap_create(h->comp, h->on_swap);hb->head = x->child;heap_union(h, hb);return x;}//将二项堆中的某一结点x的关键字减少为一个新值k,如果k大于x的当前关键字值,直接返回void heap_decrease_key(heap h, struct heap_node *x){struct heap_node *y = x;struct heap_node *z = y->parent;while (z != NULL && h->comp(y->key, z->key) < 0) {swap(&y->key, &z->key, sizeof(void *));if (h->on_swap != NULL) {h->on_swap(y, z);}y = z;z = y->parent;}}void display_node(struct heap_node *x, void (*print_key) (const void *)){print_key(x->key);printf(" ");if (x->child != NULL) {display_node(x->child, print_key);}if (x->sibling != NULL) {display_node(x->sibling, print_key);}}void heap_display(heap h, void (*print_key) (const void *)){display_node(h->head, print_key);printf("\n");}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 on_swap(struct heap_node *left, struct heap_node *right){printf("%d和%d发生了交换\n", *(int *)left->key,       *(int *)right->key);}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, on_swap);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, on_swap);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;}


原创粉丝点击