/** * C语言实现的斐波那契堆 * * @author skywang * @date 2014/04/05 */ #include <stdio.h> #include <stdlib.h> #include <math.h> #include <float.h> #include "fibonacci_heap.h" #if 0 #define LOG2(x) ({ unsigned int _i = 0; __asm__("bsr %1, %0" : "=r" (_i) : "r" ((x))); _i; }) #else // 注意:通过gcc编译时,要添加 -lm 选项。 #define LOG2(x) ((log((double)(x))) / (log(2.0))) #endif static FibNode *fib_heap_search(FibHeap *heap, Type key); /* * 将node从双链表移除 */ static void fib_node_remove(FibNode *node) { node->left->right = node->right; node->right->left = node->left; } /* * 将"单个节点node"加入"链表root"之前 * a …… root * a …… node …… root * * 注意: 此处node是单个节点,而root是双向链表 */ static void fib_node_add(FibNode *node, FibNode *root) { node->left = root->left; root->left->right = node; node->right = root; root->left = node; } /* * 将双向链表b链接到双向链表a的后面 * * 注意: 此处a和b都是双向链表 */ static void fib_node_cat(FibNode *a, FibNode *b) { FibNode *tmp; tmp = a->right; a->right = b->right; b->right->left = a; b->right = tmp; tmp->left = b; } /* * 创建斐波那契堆 */ FibHeap* fib_heap_make() heap->keyNum = 0; heap->maxDegree = 0; heap->min = NULL; heap->cons = NULL; return heap; } /* * 创建斐波那契堆的节点 */ static FibNode* fib_node_make(Type key) node->key = key; node->degree = 0; node->left = node; node->right = node; node->parent = NULL; node->child = NULL; return node; } /* * 将节点node插入到斐波那契堆heap中 */ static void fib_heap_insert_node(FibHeap *heap, FibNode *node) heap->keyNum++; } /* * 新建键值为key的节点,并将其插入到斐波那契堆中 */ void fib_heap_insert_key(FibHeap *heap, Type key) /* * 将h1, h2合并成一个堆,并返回合并后的堆 */ FibHeap* fib_heap_union(FibHeap *h1, FibHeap *h2) if((h1->min) == NULL) // h1无"最小节点" { h1->min = h2->min; h1->keyNum = h2->keyNum; free(h2->cons); free(h2); } else if((h2->min) == NULL) // h1有"最小节点" && h2无"最小节点" { free(h2->cons); free(h2); } // h1有"最小节点" && h2有"最小节点" else return h1; } /* * 将"堆的最小结点"从根链表中移除, * 这意味着"将最小节点所属的树"从堆中移除! */ static FibNode *fib_heap_remove_min(FibHeap *heap) min->left = min->right = min; return min; } /* * 将node链接到root根结点 */ static void fib_heap_link(FibHeap * heap, FibNode * node, FibNode *root) /* * 创建fib_heap_consolidate所需空间 */ static void fib_heap_cons_make(FibHeap * heap) /* * 合并斐波那契堆的根链表中左右相同度数的树 */ static void fib_heap_consolidate(FibHeap *heap) fib_heap_link(heap, y, x); // 将y链接到x中 heap->cons[d] = NULL; d++; } heap->cons[d] = x; } heap->min = NULL; // 将heap->cons中的结点重新加到根表中 for (i=0; i<D; i++) } } } /* * 移除最小节点,并返回移除节点后的斐波那契堆 */ FibNode* _fib_heap_extract_min(FibHeap *heap) // 将min从根链表中移除 fib_node_remove(min); // 若min是堆中唯一节点,则设置堆的最小节点为NULL; // 否则,设置堆的最小节点为一个非空节点(min->right),然后再进行调节。 if (min->right == min) heap->min = NULL; else { heap->min = min->right; fib_heap_consolidate(heap); } heap->keyNum--; return min; } void fib_heap_extract_min(FibHeap *heap) /* * 在斐波那契堆heap中是否存在键值为key的节点;存在返回1,否则返回0。 */ int fib_heap_get_min(FibHeap *heap, Type *pkey) /* * 修改度数 */ static void renew_degree(FibNode *parent, int degree) /* * 将node从父节点parent的子链接中剥离出来, * 并使node成为"堆的根链表"中的一员。 */ static void fib_heap_cut(FibHeap *heap, FibNode *node, FibNode *parent) /* * 对节点node进行"级联剪切" * * 级联剪切:如果减小后的结点破坏了最小堆性质, * 则把它切下来(即从所在双向链表中删除,并将 * 其插入到由最小树根节点形成的双向链表中), * 然后再从"被切节点的父节点"到所在树根节点递归执行级联剪枝 */ static void fib_heap_cascading_cut(FibHeap *heap, FibNode *node) } /* * 将斐波那契堆heap中节点node的值减少为key */ static void fib_heap_decrease(FibHeap *heap, FibNode *node, Type key) node->key = key; parent = node->parent; if (parent!=NULL && node->key < parent->key) { // 将node从父节点parent中剥离出来,并将node添加到根链表中 fib_heap_cut(heap, node, parent); fib_heap_cascading_cut(heap, parent); } // 更新最小节点 if (node->key < heap->min->key) heap->min = node; } /* * 将斐波那契堆heap中节点node的值增加为key */ static void fib_heap_increase(FibHeap *heap, FibNode *node, Type key) // 将node每一个儿子(不包括孙子,重孙,...)都添加到"斐波那契堆的根链表"中 while (node->child != NULL) node->degree = 0; node->key = key; // 如果node不在根链表中, // 则将node从父节点parent的子链接中剥离出来, // 并使node成为"堆的根链表"中的一员, // 然后进行"级联剪切" // 否则,则判断是否需要更新堆的最小节点 parent = node->parent; if(parent != NULL) { fib_heap_cut(heap, node, parent); fib_heap_cascading_cut(heap, parent); } else if(heap->min == node) } } /* * 更新二项堆heap的节点node的键值为key */ void _fib_heap_update(FibHeap *heap, FibNode *node, Type key) void fib_heap_update(FibHeap *heap, Type oldkey, Type newkey) /* * 在最小堆root中查找键值为key的节点 */ static FibNode* fib_node_search(FibNode *root, Type key) else t = t->right; } while (t != root); return p; } /* * 在斐波那契堆heap中查找键值为key的节点 */ static FibNode *fib_heap_search(FibHeap *heap, Type key) /* * 在斐波那契堆heap中是否存在键值为key的节点。 * 存在返回1,否则返回0。 */ int fib_heap_contains(FibHeap *heap, Type key) { return fib_heap_search(heap,key)!=NULL ? 1: 0; } /* * 删除结点node */ static void _fib_heap_delete(FibHeap *heap, FibNode *node) { Type min = heap->min->key; fib_heap_decrease(heap, node, min-1); _fib_heap_extract_min(heap); free(node); } void fib_heap_delete(FibHeap *heap, Type key) /* * 销毁斐波那契堆 */ static void fib_node_destroy(FibNode *node) while(node != start); } void fib_heap_destroy(FibHeap *heap) { fib_node_destroy(heap->min); free(heap->cons); free(heap); } /* * 打印"斐波那契堆" * * 参数说明: * node -- 当前节点 * prev -- 当前节点的前一个节点(父节点or兄弟节点) * direction -- 1,表示当前节点是一个左孩子; * 2,表示当前节点是一个兄弟节点。 */ static void _fib_print(FibNode *node, FibNode *prev, int direction) while(node != start); } void fib_print(FibHeap *heap) while (p != heap->min); printf(" "); }
hb是拿什么语言斐波那契堆(一)之 图文解析 和 C语言的实现
未经允许不得转载:上海聚慕医疗器械有限公司 » hb是拿什么语言斐波那契堆(一)之 图文解析 和 C语言的实现








