在计算机科学中,二项堆(Binomial Heap)是一种高效实现优先队列的数据结构。它支持合并、插入、删除最小值等操作,并且在最坏情况下具有良好的时间复杂度。本教程将带你从零开始,用Java语言实现一个完整的二项堆,即使是编程小白也能轻松理解。
二项堆是由若干棵二项树(Binomial Tree)组成的森林。每棵二项树都满足最小堆性质:父节点的值小于或等于其子节点的值。
二项树 Bk 的定义如下:

二项堆支持以下主要操作(均摊时间复杂度):
insert(x):O(log n)findMin():O(log n)deleteMin():O(log n)merge(heap):O(log n)下面我们用 Java 实现一个简化但功能完整的二项堆。首先定义二项树的节点类:
class BinomialNode { int key; int degree; // 子树数量 BinomialNode parent; BinomialNode child; BinomialNode sibling; public BinomialNode(int key) { this.key = key; this.degree = 0; this.parent = null; this.child = null; this.sibling = null; }}接着,我们实现二项堆的主体类:
import java.util.*;public class BinomialHeap { private BinomialNode head; public BinomialHeap() { this.head = null; } // 合并两个二项堆(核心操作) public void merge(BinomialHeap other) { this.head = mergeRoots(this.head, other.head); if (this.head == null) return; BinomialNode prev = null; BinomialNode x = this.head; BinomialNode next = x.sibling; while (next != null) { if (x.degree != next.degree || (next.sibling != null && next.sibling.degree == x.degree)) { prev = x; x = next; } else if (x.key <= next.key) { x.sibling = next.sibling; link(next, x); } else { if (prev == null) this.head = next; else prev.sibling = next; link(x, next); x = next; } next = x.sibling; } } // 将 y 链接到 x 下(x 成为 y 的父节点) private void link(BinomialNode y, BinomialNode x) { y.parent = x; y.sibling = x.child; x.child = y; x.degree++; } // 合并两个根链表(按 degree 升序) private BinomialNode mergeRoots(BinomialNode h2, BinomialNode h2) { if (h2 == null) return h2; if (h2 == null) return h2; BinomialNode head = null; BinomialNode tail = null; while (h2 != null && h2 != null) { if (h2.degree <= h2.degree) { if (head == null) { head = h2; tail = h2; } else { tail.sibling = h2; tail = h2; } h2 = h2.sibling; } else { if (head == null) { head = h2; tail = h2; } else { tail.sibling = h2; tail = h2; } h2 = h2.sibling; } } if (h2 != null) tail.sibling = h2; if (h2 != null) tail.sibling = h2; return head; } // 插入新元素 public void insert(int key) { BinomialHeap newHeap = new BinomialHeap(); newHeap.head = new BinomialNode(key); merge(newHeap); } // 查找最小值 public int findMin() { if (head == null) throw new RuntimeException("Heap is empty"); BinomialNode min = head; BinomialNode x = head.sibling; while (x != null) { if (x.key < min.key) { min = x; } x = x.sibling; } return min.key; } // 删除最小值 public int deleteMin() { if (head == null) throw new RuntimeException("Heap is empty"); // 找到最小根节点 BinomialNode min = head; BinomialNode minPrev = null; BinomialNode x = head; BinomialNode prev = null; while (x != null) { if (x.key < min.key) { min = x; minPrev = prev; } prev = x; x = x.sibling; } // 从根链表中移除 min if (minPrev == null) { head = min.sibling; } else { minPrev.sibling = min.sibling; } // 反转 min 的子树链表 BinomialNode child = min.child; BinomialNode revChild = null; while (child != null) { BinomialNode next = child.sibling; child.sibling = revChild; revChild = child; child = next; } // 合并反转后的子树 BinomialHeap newHeap = new BinomialHeap(); newHeap.head = revChild; merge(newHeap); return min.key; }}下面是一个简单的使用示例,演示如何创建二项堆并执行基本操作:
public class Main { public static void main(String[] args) { BinomialHeap heap = new BinomialHeap(); heap.insert(10); heap.insert(5); heap.insert(20); heap.insert(3); System.out.println("Min: " + heap.findMin()); // 输出 3 heap.deleteMin(); System.out.println("New Min: " + heap.findMin()); // 输出 5 }}相比普通的二叉堆,二项堆的最大优势在于高效的合并操作。如果你的应用场景需要频繁合并多个优先队列(例如在图算法或任务调度系统中),那么Java二项堆是一个非常合适的选择。
此外,二项堆是学习更高级数据结构(如斐波那契堆)的重要基础。掌握它有助于你深入理解数据结构教程中的高级主题。
通过本教程,你已经学会了:
希望这篇关于优先队列Java实现的详细指南能帮助你打下坚实的数据结构基础!继续练习,尝试扩展功能(如 decreaseKey),你会对算法有更深的理解。
本文由主机测评网于2025-12-15发表在主机测评网_免费VPS_免费云服务器_免费独立服务器,如有疑问,请联系我们。
本文链接:https://vpshk.cn/2025127872.html