1 | using System;
|
---|
2 | using System.Collections.Generic;
|
---|
3 | using HeuristicLab.Algorithms.GraphRouting.Interfaces;
|
---|
4 |
|
---|
5 | namespace HeuristicLab.Algorithms.GraphRouting.PriorityQueues {
|
---|
6 | public sealed class FibonacciHeap<K, V> : IHeap<K, V>
|
---|
7 | where K : IComparable
|
---|
8 | where V : IComparable {
|
---|
9 |
|
---|
10 | private HeapNode min;
|
---|
11 | private int size;
|
---|
12 |
|
---|
13 | public int Size {
|
---|
14 | get { return size; }
|
---|
15 | }
|
---|
16 |
|
---|
17 | public FibonacciHeap() {
|
---|
18 | size = 0;
|
---|
19 | min = null;
|
---|
20 | }
|
---|
21 |
|
---|
22 | public KeyValuePair<K, V> PeekMin() {
|
---|
23 | if (size == 0) {
|
---|
24 | throw new InvalidOperationException("Heap is empty");
|
---|
25 | }
|
---|
26 | KeyValuePair<K, V> pair = new KeyValuePair<K, V>(min.Key, min.Value);
|
---|
27 | return pair;
|
---|
28 | }
|
---|
29 |
|
---|
30 | public K PeekMinKey() {
|
---|
31 | if (size == 0) {
|
---|
32 | throw new InvalidOperationException("Heap is empty");
|
---|
33 | }
|
---|
34 | return min.Key;
|
---|
35 | }
|
---|
36 |
|
---|
37 | public V PeekMinValue() {
|
---|
38 | if (size == 0) {
|
---|
39 | throw new InvalidOperationException("Heap is empty");
|
---|
40 | }
|
---|
41 | return min.Value;
|
---|
42 | }
|
---|
43 |
|
---|
44 | public void Insert(K key, V value) {
|
---|
45 | HeapNode n = new HeapNode(key, value);
|
---|
46 | if (min == null) {
|
---|
47 | min = n;
|
---|
48 | } else {
|
---|
49 | // concateneate the root list (becoming left sibling of root)
|
---|
50 | n.Right = min;
|
---|
51 | n.Left = min.Left;
|
---|
52 | n.Right.Left = n;
|
---|
53 | n.Left.Right = n;
|
---|
54 | // update point of minimum if necessary
|
---|
55 | if (n.Key.CompareTo(min.Key) < 0) {
|
---|
56 | min = n;
|
---|
57 | }
|
---|
58 | }
|
---|
59 | size++;
|
---|
60 | }
|
---|
61 |
|
---|
62 | public void DecreaseKey(K key, V value) {
|
---|
63 | throw new NotImplementedException();
|
---|
64 | }
|
---|
65 |
|
---|
66 | public void RemoveMin() {
|
---|
67 | if (size == 0) {
|
---|
68 | throw new InvalidOperationException("Heap is empty");
|
---|
69 | }
|
---|
70 | HeapNode z = min;
|
---|
71 | if (z.Child != null) {
|
---|
72 | // set all z's childs parent to null ...
|
---|
73 | z.Child.Parent = null;
|
---|
74 | HeapNode x = z.Child.Right;
|
---|
75 | while (x != z.Child) {
|
---|
76 | x.Parent = null;
|
---|
77 | x = x.Right;
|
---|
78 | }
|
---|
79 | // ... and make all of them roots
|
---|
80 | HeapNode minLeft = min.Left;
|
---|
81 | min.Left = z.Child.Left;
|
---|
82 | min.Left.Right = min;
|
---|
83 | z.Child.Left = minLeft;
|
---|
84 | minLeft.Right = z.Child;
|
---|
85 | }
|
---|
86 |
|
---|
87 | // remove z frome root list
|
---|
88 | z.Left.Right = z.Right;
|
---|
89 | z.Right.Left = z.Left;
|
---|
90 |
|
---|
91 | if (z == z.Right) {
|
---|
92 | min = null;
|
---|
93 | } else {
|
---|
94 | // point min to a node other than z
|
---|
95 | // (not necessarily going to be the new minimum)
|
---|
96 | min = z.Right;
|
---|
97 | Consolidate();
|
---|
98 | }
|
---|
99 | size--;
|
---|
100 |
|
---|
101 | //var zNode = new KeyValuePair<K, V>(z.Key, z.Value);
|
---|
102 | z = null;
|
---|
103 | //return zNode;
|
---|
104 | }
|
---|
105 |
|
---|
106 | private void Link(HeapNode y, HeapNode z) {
|
---|
107 | // remove y from the root list
|
---|
108 | y.Left.Right = y.Right;
|
---|
109 | y.Right.Left = y.Left;
|
---|
110 |
|
---|
111 | // make y a child of x, ...
|
---|
112 | y.Parent = z;
|
---|
113 | if (z.Child == null) {
|
---|
114 | z.Child = y;
|
---|
115 | y.Right = y;
|
---|
116 | y.Left = y;
|
---|
117 | } else {
|
---|
118 | y.Left = z.Child;
|
---|
119 | y.Right = z.Child.Right;
|
---|
120 | z.Child.Right = y;
|
---|
121 | y.Right.Left = y;
|
---|
122 | }
|
---|
123 |
|
---|
124 | // ... incrementing degree[x]
|
---|
125 | z.Degree++;
|
---|
126 | y.Mark = false;
|
---|
127 | }
|
---|
128 |
|
---|
129 | private void Consolidate() {
|
---|
130 | int dn = (int)Math.Floor(Math.Log(size) / Math.Log(2)) + 1; // log2size[Heap]
|
---|
131 | HeapNode[] A = new HeapNode[dn]; // consolidation array
|
---|
132 | HeapNode start = min;
|
---|
133 | HeapNode w = min;
|
---|
134 |
|
---|
135 | // for each node w in the root list
|
---|
136 | do {
|
---|
137 | HeapNode x = w;
|
---|
138 | HeapNode nextW = w.Right;
|
---|
139 | int d = x.Degree;
|
---|
140 |
|
---|
141 | while (A[d] != null) {
|
---|
142 | HeapNode y = A[d]; // another node with the same degree as x
|
---|
143 | if (x.Key.CompareTo(y.Key) > 0) {
|
---|
144 | // exchange x <-> y
|
---|
145 | HeapNode tmp = x;
|
---|
146 | x = y;
|
---|
147 | y = tmp;
|
---|
148 | }
|
---|
149 | if (y == start) {
|
---|
150 | start = start.Right;
|
---|
151 | }
|
---|
152 | if (y == nextW) {
|
---|
153 | nextW = nextW.Right;
|
---|
154 | }
|
---|
155 | Link(y, x);
|
---|
156 | A[d] = null;
|
---|
157 | d++;
|
---|
158 | }
|
---|
159 |
|
---|
160 | A[d] = x;
|
---|
161 | w = nextW;
|
---|
162 | } while (w != start);
|
---|
163 |
|
---|
164 | min = null;
|
---|
165 |
|
---|
166 | // find the new minimum key
|
---|
167 | for (int i = 0; i < dn; i++) {
|
---|
168 | if (A[i] != null) {
|
---|
169 | HeapNode n = A[i];
|
---|
170 | if (min == null) {
|
---|
171 | min = n;
|
---|
172 | } else {
|
---|
173 | if (n.Key.CompareTo(min.Key) < 0) {
|
---|
174 | min = n;
|
---|
175 | }
|
---|
176 | }
|
---|
177 | }
|
---|
178 | }
|
---|
179 | }
|
---|
180 |
|
---|
181 | private class HeapNode {
|
---|
182 | public K Key;
|
---|
183 | public V Value;
|
---|
184 | public int Degree;
|
---|
185 | public bool Mark;
|
---|
186 | public HeapNode Left;
|
---|
187 | public HeapNode Right;
|
---|
188 | public HeapNode Parent;
|
---|
189 | public HeapNode Child;
|
---|
190 |
|
---|
191 | public HeapNode(K key, V value) {
|
---|
192 | this.Key = key;
|
---|
193 | this.Value = value;
|
---|
194 | this.Right = this;
|
---|
195 | this.Left = this;
|
---|
196 | this.Parent = null;
|
---|
197 | this.Child = null;
|
---|
198 | this.Degree = 0;
|
---|
199 | this.Mark = false;
|
---|
200 | }
|
---|
201 | }
|
---|
202 | }
|
---|
203 | }
|
---|