斐波那契堆由最小堆性质的树构成,通过循环双向链表连接根节点,支持O(1)摊还时间的插入与合并操作,提取最小值为O(log n),适用于频繁合并场景。

斐波那契堆是一种高级优先队列结构,支持插入、查找最小值、合并、提取最小值和减小键值等操作,其中合并和插入的摊还时间复杂度为 O(1),提取最小值为 O(log n)。相比二叉堆,它在需要频繁合并堆的场景中更高效。
基本原理与结构设计
斐波那契堆由一组满足最小堆性质的树组成,这些树以循环双向链表连接。每个节点包含以下信息:
key:存储的数据值degree:子节点数量marked:标记节点是否丢失过一个子节点parent, child, left, right:用于构建树和根链表的指针
堆整体维护一个指向最小节点的指针,并通过级联剪枝和度数压缩优化性能。
C++ 实现关键部分
以下是简化但核心功能完整的实现框架:
立即学习“C++免费学习笔记(深入)”;
// 节点定义struct FibNode { int key; int degree; bool marked; FibNode* parent; FibNode* child; FibNode* left; FibNode* right;
explicit FibNode(int k) : key(k), degree(0), marked(false), parent(nullptr), child(nullptr) { left = right = this;}
};
// 斐波那契堆类(简化版)class FibonacciHeap {private:FibNode* min_node;int size;
// 将y链接为x的子节点void link(FibNode* y, FibNode* x) { // 从根链表移除y remove_from_list(y); y->parent = x; if (!x->child) { x->child = y; y->left = y->right = y; } else { add_to_list(y, x->child); } x->degree++; y->marked = false;}// 合并根链表到数组,进行合并操作void consolidate() { if (!min_node) return; int max_degree = 0; int sz = size + 1; while ((1 << max_degree) <= sz) max_degree++; std::vector A(max_degree, nullptr); auto roots = get_root_list(); for (FibNode* w : roots) { int d = w->degree; while (A[d]) { FibNode* u = A[d]; if (w->key > u->key) std::swap(w, u); link(u, w); A[d] = nullptr; d++; } A[d] = w; } // 重建根链表并找新的最小值 min_node = nullptr; for (FibNode* node : A) { if (!node) continue; if (!min_node) { min_node = node; min_node->left = min_node->right = node; } else { add_to_list(node, min_node); if (node->key key) { min_node = node; } } }}// 从双链表中移除节点void remove_from_list(FibNode* node) { node->left->right = node->right; node->right->left = node->left;}// 将节点加入某链表(以anchor为头)void add_to_list(FibNode* node, FibNode* anchor) { node->left = anchor; node->right = anchor->right; anchor->right->left = node; anchor->right = node;}// 获取当前所有根节点std::vector get_root_list() { std::vector roots; if (!min_node) return roots; FibNode* curr = min_node; do { roots.push_back(curr); curr = curr->right; } while (curr != min_node); return roots;}
public:FibonacciHeap() : min_node(nullptr), size(0) {}
~FibonacciHeap() { // 简化:实际应递归释放所有节点 while (min_node) extract_min();}bool empty() const { return min_node == nullptr; }int top() const { if (!min_node) throw std::runtime_error("Heap is empty"); return min_node->key;}void push(int key) { FibNode* node = new FibNode(key); if (!min_node) { min_node = node; } else { add_to_list(node, min_node); if (node->key key) { min_node = node; } } size++;}int extract_min() { if (!min_node) throw std::runtime_error("Heap is empty"); FibNode* z = min_node; // 将z的所有子节点提升为根 if (z->child) { auto children = get_children(z); for (FibNode* child : children) { add_to_list(child, min_node); child->parent = nullptr; } } remove_from_list(z); int res = z->key; if (z == z->right) { min_node = nullptr; } else { min_node = z->right; consolidate(); } delete z; size--; return res;}// 获取某个节点的所有子节点std::vector get_children(FibNode* node) { std::vector result; if (!node->child) return result; FibNode* curr = node->child; do { result.push_back(curr); curr = curr->right; } while (curr != node->child); return result;}// 合并另一个堆(O(1) 摊还时间)void merge(FibonacciHeap& other) { if (other.min_node == nullptr) return; if (min_node == nullptr) { *this = std::move(other); return; } // 拼接两个根链表 FibNode* this_left = min_node->left; FibNode* other_right = other.min_node->right; min_node->left->right = other.min_node; other.min_node->left->right = min_node; FibNode* tmp = min_node->left; min_node->left = other.min_node->left; other.min_node->left = tmp; if (other.min_node->key key) { min_node = other.min_node; } size += other.size; other.min_node = nullptr; other.size = 0;}
};
使用示例与注意事项
下面是一个简单的测试用法:
int main() { FibonacciHeap heap1, heap2;
heap1.push(5);heap1.push(2);heap1.push(8);heap2.push(3);heap2.push(7);heap1.merge(heap2); // O(1)while (!heap1.empty()) { std::cout << heap1.extract_min() << " ";}// 输出: 2 3 5 7 8
}
注意:上述实现省略了 decrease_key 和 delete 操作,它们依赖于标记机制和级联剪枝,在图算法如 Dijkstra 中非常关键。生产环境需增加内存管理、异常安全和模板泛型支持。
基本上就这些,理解其摊还分析和树合并策略是掌握的关键。
以上就是C++怎么实现一个斐波那契堆_C++具有高效合并操作的优先队列数据结构的详细内容,更多请关注创想鸟其它相关文章!
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 chuangxiangniao@163.com 举报,一经查实,本站将立刻删除。
发布者:程序猿,转转请注明出处:https://www.chuangxiangniao.com/p/1488194.html
微信扫一扫
支付宝扫一扫