///|
/// 创建一个新的空斐波那契堆
pub fn[A, K] new(compare : (K, K) -> Int) -> FibHeap[A, K] {
FibHeap::{ size: 0, min: Node::Nil, roots: 0, compare }
}
///|
/// 检查堆是否为空
pub fn[A, K] is_empty(self : FibHeap[A, K]) -> Bool {
self.size == 0
}
///|
/// 获取堆中元素数量
pub fn[A, K] size(self : FibHeap[A, K]) -> Int {
self.size
}
///|
/// 从数组创建斐波那契堆
pub fn[A : Eq, K : Eq] from_array(
arr : Array[A],
keys : Array[K],
compare : (K, K) -> Int,
) -> FibHeap[A, K] {
let heap = new(compare)
let len = @cmp.minimum(arr.length(), keys.length())
for i in 0.. Unit {
match (heap.min, node) {
(Node::Nil, Node::Cons(..) as n) =>
// 空堆,节点成为唯一的根
make_singleton(n)
(Node::Cons(..) as min, Node::Cons(..) as n) => {
// 插入到最小节点和其右侧节点之间
let right = get_right(min)
connect_right(min, n)
connect_right(n, right)
}
_ => () // 至少有一个是 Nil,不做任何操作
}
heap.roots += 1
}
///| 从根链表中移除节点
pub fn[A : Eq, K : Eq] remove_from_root_list(
heap : FibHeap[A, K],
node : Node[A, K],
) -> Unit {
match node {
Node::Nil => ()
Node::Cons(..) as n => {
if get_right(n) == n {
heap.min = Node::Nil
} else {
let left = get_left(n)
let right = get_right(n)
match (left, right) {
(Node::Cons(..) as l, Node::Cons(..) as r) => {
l.right = r
r.left = l
}
_ => ()
}
if heap.min == n {
heap.min = right
}
}
heap.roots -= 1
}
}
}
///| 比较两个节点的键值
pub fn[A, K] is_less(
heap : FibHeap[A, K],
a : Node[A, K],
b : Node[A, K],
) -> Bool {
match (a, b) {
(Node::Cons(..) as node_a, Node::Cons(..) as node_b) =>
(heap.compare)(node_a.key, node_b.key) < 0
_ => false
}
}
///|
pub fn[A : Eq, K : Eq] add_children_to_root_list(
heap : FibHeap[A, K],
parent : Node[A, K],
) -> Unit {
match parent {
Node::Nil => ()
Node::Cons(..) as p => {
let child = get_child(p)
match child {
Node::Nil => ()
Node::Cons(..) as first_child => {
let children = Array::new()
let mut curr = first_child
let mut count = 0
let max_count = p.degree + 2 // 安全上限,防止死循环
// 使用do-while逻辑:先处理第一个节点,然后循环直到回到起点
while true {
children.push(curr)
curr = get_right(curr)
count += 1
// 安全检查:防止无限循环
if count > max_count || curr == first_child {
break
}
}
for i in 0.. {
child_node.parent = Node::Nil
reset_mark(child_node)
add_to_root_list(heap, child_node)
}
Node::Nil => ()
}
}
}
}
clear_children(p)
}
}
}
///| 将子节点链接到父节点
pub fn[A : Eq, K : Eq] link(
heap : FibHeap[A, K],
child : Node[A, K],
parent : Node[A, K],
) -> Unit {
match (parent, child) {
(Node::Cons(..) as p, Node::Cons(..) as c) => {
// 从根链表中移除child
remove_from_root_list(heap, c)
// 将child添加为parent的子节点
add_child(p, c)
}
_ => () // 至少有一个是 Nil,不做任何操作
}
}
///| 剪切操作:将节点从父节点分离并添加到根链表
pub fn[A : Eq, K : Eq] cut(
heap : FibHeap[A, K],
node : Node[A, K],
parent : Node[A, K],
) -> Unit {
match (node, parent) {
(Node::Cons(..) as n, Node::Cons(..) as p) => {
// 从父节点的子链表中移除
if get_right(n) == n {
// 唯一的子节点
p.child = Node::Nil
} else {
// 将左右节点连接起来
let left = get_left(n)
let right = get_right(n)
connect_right(left, right)
// 如果移除的是父节点的直接子节点,需要更新child引用
if p.child == n {
p.child = right
}
}
p.degree -= 1
// 添加到根链表
add_to_root_list(heap, n)
n.parent = Node::Nil
reset_mark(n)
}
_ => () // 至少有一个是 Nil,不做任何操作
}
}
///| 级联剪切:处理被标记的节点
pub fn[A : Eq, K : Eq] cascading_cut(
heap : FibHeap[A, K],
node : Node[A, K],
) -> Unit {
match node {
Node::Nil => ()
Node::Cons(..) as n => {
let parent = get_parent(n)
match parent {
Node::Nil => () // 根节点,不需要处理
Node::Cons(..) as p =>
if !is_marked(n) {
// 第一次失去子节点,标记它
mark_node(n)
} else {
// 已经被标记,执行剪切并对父节点进行级联剪切
cut(heap, n, p)
cascading_cut(heap, p)
}
}
}
}
}
///| 合并根链表中具有相同度数的树
pub fn[A : Eq, K : Eq] consolidate(heap : FibHeap[A, K]) -> Unit {
if heap.size == 0 || heap.min == Node::Nil {
return
}
// 创建度数数组
let max_degree = @math.log2(heap.size.to_double()).ceil().to_int() + 1
let degree_array = Array::makei(max_degree, _ => Node::Nil)
// 收集所有根节点到数组中,防止在处理过程中链表结构改变导致循环出错
let root_nodes = Array::new(capacity=heap.roots)
let start = heap.min
let mut current = start
let mut counter = 0
// 安全地收集所有根节点
while counter < heap.roots {
root_nodes.push(current)
current = get_right(current)
counter += 1
// 安全检查,防止无限循环
if counter > heap.size {
break // 紧急退出
}
}
// 清空根链表
heap.min = Node::Nil
heap.roots = 0
// 处理收集到的每个根节点
for i in 0.. {
degree = n.degree
// 确保节点的左右指针指向自身(成为单节点循环链表)
n.left = n
n.right = n
// 合并相同度数的树
while degree < degree_array.length() &&
degree_array[degree] != Node::Nil {
let mut same_degree = degree_array[degree]
// 确保node是键值较小的那个
if is_less(heap, same_degree, node) {
let temp = node
node = same_degree
same_degree = temp
}
// 将same_degree作为node的子节点
match (node, same_degree) {
(Node::Cons(..) as parent, Node::Cons(..) as child) => {
// 设置父子关系
child.parent = parent
reset_mark(child)
// 添加到子链表
if parent.child == Node::Nil {
parent.child = child
child.left = child
child.right = child
} else {
let first_child = parent.child
match first_child {
Node::Cons(..) as fc => {
let right = fc.right
child.right = right
child.left = fc
fc.right = child
match right {
Node::Cons(..) as r => r.left = child
Node::Nil => () // 不应该发生
}
}
Node::Nil => () // 不应该发生
}
}
parent.degree += 1
}
_ => () // 不应该发生
}
// 清除度数槽,继续检查下一个度数
degree_array[degree] = Node::Nil
degree += 1
}
// 将处理后的节点放入对应度数槽
if degree < degree_array.length() {
degree_array[degree] = node
}
}
Node::Nil => () // 不应该发生
}
}
// 重建根链表
for i in 0.. Node[A, K] {
// 使用辅助函数创建新节点
let node = create_node(value, key)
// 将新节点添加到根链表
if self.min == Node::Nil {
// 堆为空
self.min = node
self.roots = 1
} else {
// 添加到根链表
add_to_root_list(self, node)
// 更新最小节点
if is_less(self, node, self.min) {
self.min = node
}
}
self.size += 1
node
}
///| 查看最小键值元素
pub fn[A, K] peek_min(self : FibHeap[A, K]) -> (A, K)? {
match self.min {
Node::Nil => None
Node::Cons(..) as cons_node => Some((cons_node.content, cons_node.key))
}
}
///| 提取最小键值元素
pub fn[A : Eq, K : Eq] extract_min(self : FibHeap[A, K]) -> (A, K)? {
if self.min == Node::Nil {
return None
}
// 获取最小节点
let min_node = self.min
// 先保存要返回的值
let result = match min_node {
Node::Nil => return None
Node::Cons(..) as cons_node => (cons_node.content, cons_node.key)
}
// 如果有子节点,将它们添加到根链表
match min_node {
Node::Cons(..) as min => {
// 使用数组收集所有子节点,避免在修改过程中遍历链表
let children = Array::new()
let child = min.child
match child {
Node::Nil => ()
Node::Cons(..) as first_child => {
let mut curr = first_child
let count = min.degree
// 收集所有子节点
for _ in 0.. {
// 重置父节点和标记
child_node.parent = Node::Nil
reset_mark(child_node)
// 确保节点形成单独的循环
child_node.left = child_node
child_node.right = child_node
// 添加到根链表
add_to_root_list(self, child_node)
}
Node::Nil => () // 不应该发生
}
}
}
}
}
Node::Nil => () // 不应该发生
}
// 从根链表中移除最小节点
remove_from_list(min_node)
self.roots -= 1
// 如果根链表为空,设置min为空
if self.roots == 0 {
self.min = Node::Nil
} else {
// 查找新的最小节点 - 从右侧节点开始
let next = get_right(min_node)
self.min = next
let mut current = next
let mut counter = 0
while counter < self.roots {
if is_less(self, current, self.min) {
self.min = current
}
current = get_right(current)
counter += 1
// 安全检查
if counter > self.size {
break
}
}
}
// 更新堆大小
self.size -= 1
// 合并具有相同度数的树
if self.roots > 1 {
consolidate(self)
}
// 返回保存的结果
Some(result)
}
///| 减小节点的键值
pub fn[A : Eq, K : Eq] decrease_key(
self : FibHeap[A, K],
node : Node[A, K],
new_key : K,
) -> Bool {
match node {
Node::Nil => false
Node::Cons(..) as cons_node => {
// 检查新键是否更小
if (self.compare)(new_key, cons_node.key) >= 0 {
// 新键值不小于当前键值
return false
}
// 提取节点的值
let value = cons_node.content
// 删除旧节点
if self.delete(node) {
// 插入具有相同值但新键的节点
ignore(self.insert(value, new_key))
return true
}
false
}
}
}
///| 删除节点(不依赖极小值)
pub fn[A : Eq, K : Eq] delete(self : FibHeap[A, K], node : Node[A, K]) -> Bool {
match node {
Node::Nil => false
Node::Cons(..) as cons_node => {
// 如果节点有父节点,从父节点剪切出来
let parent = get_parent(cons_node)
if parent != Node::Nil {
match parent {
Node::Cons(..) as p => {
// 从父节点的子链表中移除
if p.child == cons_node {
if get_right(cons_node) == cons_node {
// 唯一的子节点
p.child = Node::Nil
} else {
p.child = get_right(cons_node)
}
}
// 断开左右连接
remove_from_list(cons_node)
// 减少父节点的度数
p.degree -= 1
// 将被删除节点的子节点添加到根链表
add_children_to_root_list(self, cons_node)
}
Node::Nil => () // 不应该发生
}
self.size -= 1
} else if self.min == node {
// 是根节点且是最小节点
ignore(self.extract_min())
return true // extract_min已经处理了size减法
} else {
// 是根节点但不是最小节点
remove_from_root_list(self, node)
add_children_to_root_list(self, node)
self.size -= 1
}
true
}
}
}
///| 合并两个斐波那契堆
pub fn[A : Eq, K : Eq] merge(
self : FibHeap[A, K],
other : FibHeap[A, K],
) -> Unit {
// 如果other为空,不需要操作
if other.min == Node::Nil {
return
}
// 如果self为空,直接采用other
if self.min == Node::Nil {
self.min = other.min
self.size = other.size
self.roots = other.roots
return
}
if self == other {
// 合并自身,无操作
return
}
// 连接两个根链表
let selfMin = self.min
let otherMin = other.min
// 使用辅助函数连接两个链表
let selfRight = get_right(selfMin)
let otherRight = get_right(otherMin)
connect_right(selfMin, otherRight)
connect_right(otherMin, selfRight)
// 更新最小节点
if is_less(self, otherMin, selfMin) {
self.min = otherMin
}
// 更新堆的大小和根节点数量
self.size += other.size
self.roots += other.roots
}
///| 初始化节点为独立节点(设置自循环指针)
pub fn[A, K] make_singleton(node : Node[A, K]) -> Unit {
match node {
Node::Nil => ()
Node::Cons(..) as cons_node => {
cons_node.left = cons_node // 使用已绑定的cons_node,而不是node
cons_node.right = cons_node
cons_node.parent = Node::Nil
cons_node.child = Node::Nil
}
}
}
///| 安全地设置左右指针
pub fn[A, K] connect_right(node : Node[A, K], right_node : Node[A, K]) -> Unit {
match (node, right_node) {
(Node::Cons(..) as left, Node::Cons(..) as right) => {
left.right = right
right.left = left
}
_ => () // 至少有一个是 Nil,不做任何操作
}
}
///| 将一个节点作为另一个节点的子节点
pub fn[A, K] add_child(parent : Node[A, K], child : Node[A, K]) -> Unit {
match (parent, child) {
(Node::Cons(..) as p, Node::Cons(..) as c) => {
// 设置父子关系
c.parent = p
match p.child {
Node::Nil => {
// 父节点还没有子节点
p.child = c
make_singleton(c)
}
Node::Cons(..) as first_child => {
// 添加到现有子链表
let first_right = first_child.right
connect_right(first_child, c)
connect_right(c, first_right)
}
}
// 增加父节点的degree
p.degree += 1
}
_ => () // 至少有一个是 Nil,不做任何操作
}
}
///| 重置节点的标记
pub fn[A, K] reset_mark(node : Node[A, K]) -> Unit {
match node {
Node::Nil => ()
Node::Cons(..) as cons_node => cons_node.marked = false
}
}
///| 设置节点的标记
pub fn[A, K] mark_node(node : Node[A, K]) -> Unit {
match node {
Node::Nil => ()
Node::Cons(..) as cons_node => cons_node.marked = true
}
}
///| 检查节点是否被标记
pub fn[A, K] is_marked(node : Node[A, K]) -> Bool {
match node {
Node::Nil => false
Node::Cons(..) as cons_node => cons_node.marked
}
}
///| 安全地获取节点的父节点
pub fn[A, K] get_parent(node : Node[A, K]) -> Node[A, K] {
match node {
Node::Nil => Node::Nil
Node::Cons(..) as cons_node => cons_node.parent
}
}
///| 安全地获取节点的子节点
pub fn[A, K] get_child(node : Node[A, K]) -> Node[A, K] {
match node {
Node::Nil => Node::Nil
Node::Cons(..) as cons_node => cons_node.child
}
}
///| 安全地获取节点的右兄弟
pub fn[A, K] get_right(node : Node[A, K]) -> Node[A, K] {
match node {
Node::Nil => Node::Nil
Node::Cons(..) as cons_node => cons_node.right
}
}
///| 安全地获取节点的左兄弟
pub fn[A, K] get_left(node : Node[A, K]) -> Node[A, K] {
match node {
Node::Nil => Node::Nil
Node::Cons(..) as cons_node => cons_node.left
}
}
///| 安全地获取节点的值和键
pub fn[A, K] get_value_and_key(node : Node[A, K]) -> (A, K)? {
match node {
Node::Nil => None
Node::Cons(..) as cons_node => Some((cons_node.content, cons_node.key))
}
}
///| 安全地从链表中移除节点
pub fn[A : Eq, K : Eq] remove_from_list(node : Node[A, K]) -> Unit {
match node {
Node::Nil => ()
Node::Cons(..) as cons_node => {
if cons_node == cons_node.right {
// 链表中只有这一个节点,不需要操作
return
}
// 将左右节点连接起来
match (cons_node.left, cons_node.right) {
(Node::Cons(..) as left, Node::Cons(..) as right) => {
left.right = right
right.left = left
}
_ => () // 不应该发生
}
}
}
}
///| 清除节点的所有子节点
pub fn[A, K] clear_children(node : Node[A, K]) -> Unit {
match node {
Node::Nil => ()
Node::Cons(..) as cons_node => {
cons_node.child = Node::Nil
cons_node.degree = 0
}
}
}
///| 创建新节点
pub fn[A, K] create_node(value : A, key : K) -> Node[A, K] {
let node = Node::Cons(
content=value,
key~,
degree=0,
marked=false,
parent=Node::Nil,
child=Node::Nil,
left=Node::Nil, // 临时值
right=Node::Nil, // 临时值
)
// 设置循环引用
match node {
Node::Nil => node // 不会发生
Node::Cons(..) as cons_node => {
cons_node.left = cons_node
cons_node.right = cons_node
cons_node
}
}
}
///| 按值查找节点,返回节点引用或 Node::Nil
pub fn[A : Eq, K : Eq] find_by_value(
self : FibHeap[A, K],
value : A,
) -> Node[A, K] {
let mut count = 0
let mut curr = self.min
while count < self.roots && curr != Node::Nil {
match curr {
Node::Cons(..) as node => {
if node.content == value {
return curr
}
curr = get_right(curr)
count += 1
}
Node::Nil => return Node::Nil
}
}
Node::Nil
}
///| 按键查找节点,返回节点引用或 Node::Nil
pub fn[A : Eq, K : Eq] find_by_key(self : FibHeap[A, K], key : K) -> Node[A, K] {
let mut count = 0
let mut curr = self.min
while count < self.roots && curr != Node::Nil {
match curr {
Node::Cons(..) as node => {
if node.key == key {
return curr
}
curr = get_right(curr)
count += 1
}
Node::Nil => break
}
}
Node::Nil
}
///| 清空堆,重置所有属性
pub fn[A, K] clear(self : FibHeap[A, K]) -> Unit {
self.size = 0
self.min = Node::Nil
self.roots = 0
}
///|
pub fn[A : Eq, K : Eq] to_array(self : FibHeap[A, K]) -> Array[(A, K)] {
let result = Array::new()
let mut count = 0
let mut curr = self.min
while count < self.roots && curr != Node::Nil {
match curr {
Node::Cons(..) as node => {
collect_node(node, result)
curr = get_right(curr)
count += 1
}
Node::Nil => break
}
}
result
}
// 递归收集节点及其所有子节点
///|
pub fn[A : Eq, K : Eq] collect_node(
node : Node[A, K],
result : Array[(A, K)],
) -> Unit {
match node {
Node::Cons(..) as n => {
result.push((n.content, n.key))
let child = get_child(n)
if child != Node::Nil {
// 遍历子链表
let mut curr = child
let mut first = true
while first || curr != child {
collect_node(curr, result)
curr = get_right(curr)
first = false
}
}
}
Node::Nil => ()
}
}
///| 支持堆的深拷贝,返回堆的完整副本
pub fn[A : Eq, K : Eq] clone(self : FibHeap[A, K]) -> FibHeap[A, K] {
let new_heap = new(self.compare)
let arr = self.to_array()
for i in 0.. Unit {
let len = @cmp.minimum(values.length(), keys.length())
for i in 0.. Array[(A, K)] {
let arr = self.to_array()
arr.sort_by((a, b) => (self.compare)(a.1, b.1))
arr
}