-
-
Notifications
You must be signed in to change notification settings - Fork 46.6k
/
Copy pathfibonacci_heap.py
101 lines (81 loc) · 2.83 KB
/
fibonacci_heap.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
class FibonacciNode:
def __init__(self, key):
self.key = key
self.children = []
self.marked = False
self.degree = 0
self.parent = None
class FibonacciHeap:
def __init__(self):
self.trees = []
self.least = None
self.count = 0
def insert(self, key):
new_node = FibonacciNode(key)
self.trees.append(new_node)
self.count += 1
if self.least is None or key < self.least.key:
self.least = new_node
def extract_min(self):
if self.count == 0:
raise ValueError("Heap is empty")
min_node = self.least
self.trees.remove(min_node)
for child in min_node.children:
child.parent = None
self.trees.append(child)
self.count -= 1
if self.least is min_node:
self.least = None
for node in self.trees:
if self.least is None or node.key < self.least.key:
self.least = node
self.consolidate()
return min_node.key
def consolidate(self):
degree_counts = [None] * (2 * len(self.trees))
for node in self.trees[:]:
degree = node.degree
while degree_counts[degree] is not None:
other_node = degree_counts[degree]
if node.key > other_node.key:
node, other_node = other_node, node # Swap nodes
self.link(other_node, node)
degree_counts[degree] = None
degree += 1
degree_counts[degree] = node
self.trees = [node for node in degree_counts if node is not None]
def link(self, node1, node2):
self.trees.remove(node2)
node1.children.append(node2)
node2.parent = node1
node1.degree += 1
node2.marked = False
def decrease_key(self, node, new_key):
if new_key > node.key:
raise ValueError("New key must be less than or equal to old key")
node.key = new_key
if node == self.least:
self.update_least()
parent = node.parent
if parent is not None and node.key < parent.key:
self.cut(node, parent)
self.cascading_cut(parent)
def cut(self, node, parent):
parent.children.remove(node)
parent.degree -= 1
self.trees.append(node)
node.parent = None
node.marked = False
def cascading_cut(self, node):
if (parent := node.parent) is not None:
if not node.marked:
node.marked = True
else:
self.cut(node, parent)
self.cascading_cut(parent)
def update_least(self):
self.least = None
for node in self.trees:
if self.least is None or node.key < self.least.key:
self.least = node