Skip to content
This repository was archived by the owner on Nov 29, 2020. It is now read-only.

Commit 0543de0

Browse files
committed
FibHeap.cpp
1 parent 4ac3599 commit 0543de0

File tree

2 files changed

+132
-14
lines changed

2 files changed

+132
-14
lines changed

FibHeap.cpp

Lines changed: 129 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -26,18 +26,65 @@
2626

2727
#include "utils.h"
2828

29+
#include "RedBlackTree.cpp"
30+
2931
template <typename T>
3032
class FNode {
3133
public:
3234
FNode(T k, FNode<T>* P): key(k), degree(0), p(P), child(nullptr),
3335
left(nullptr), right(nullptr), mark(false) {}
34-
// FNode<T>* recursive_destruct() {}
36+
FNode<T>* recursive_destruct() {
37+
while (child)
38+
delete DLLRemove(child, child)->recursive_destruct();
39+
return this;
40+
}
3541
T key;
3642
size_t degree;
3743
FNode<T> *p, *child, *left, *right;
3844
bool mark;
3945
};
4046

47+
template <typename T>
48+
class FNodeDeg {
49+
public:
50+
FNodeDeg(): data(nullptr) {}
51+
FNodeDeg(FNode<T>* d): data(d) {}
52+
bool operator<(const FNodeDeg& rhs) const {
53+
return data->degree < rhs.data->degree;
54+
}
55+
bool operator==(const FNodeDeg& rhs) const {
56+
return data->degree == rhs.data->degree;
57+
}
58+
FNode<T>* data;
59+
};
60+
61+
template <typename T>
62+
void DLLInsert(FNode<T>*& root, FNode<T>* x) {
63+
if (root) {
64+
x->left = root->left;
65+
x->left->right = x;
66+
x->right = root;
67+
root->left = x;
68+
} else {
69+
root = x;
70+
root->left = root;
71+
root->right = root;
72+
}
73+
}
74+
75+
template <typename T>
76+
FNode<T>* DLLRemove(FNode<T>*& root, FNode<T>* x) {
77+
if (root == root->right)
78+
root = nullptr;
79+
else {
80+
if (root == x)
81+
root = root->right;
82+
x->left->right = x->right;
83+
x->right->left = x->left;
84+
}
85+
return x;
86+
}
87+
4188
template <typename T>
4289
class FibHeap {
4390
public:
@@ -48,18 +95,9 @@ class FibHeap {
4895
}
4996
FNode<T>* FibHeapInsert(const T& k) {
5097
FNode<T>* x = new FNode<T>(k, nullptr);
51-
if (!min) {
52-
x->left = x;
53-
x->right = x;
98+
DLLInsert(min, x);
99+
if (x->key < min->key)
54100
min = x;
55-
} else {
56-
x->left = min->left;
57-
x->right = min;
58-
min->left = x;
59-
x->left->right = x;
60-
if (x->key < min->key)
61-
min = x;
62-
}
63101
n++;
64102
return x;
65103
}
@@ -86,7 +124,71 @@ class FibHeap {
86124
rhs.MakeFibHeap();
87125
return H;
88126
}
89-
// ~FibHeap() { if (min) { delete min->recursive_destruct(); } }
127+
FNode<T>* FibHeapLink(FNode<T>* x, FNode<T>* y) {
128+
if (x->key > y->key)
129+
std::swap(x, y);
130+
DLLInsert(x->child, y);
131+
x->degree++;
132+
y->mark = false;
133+
return x;
134+
}
135+
void Consolidate() {
136+
RedBlackTree<FNodeDeg<T>> A;
137+
while (min) {
138+
FNode<T>* x = DLLRemove(min, min);
139+
while (true) {
140+
Node<CData<FNodeDeg<T>>>* Y = A.TreeSearch(FNodeDeg<T>(x));
141+
if (Y == A.nil)
142+
break;
143+
FNode<T>* y = Y->data.data.data;
144+
A.RBDelete(Y);
145+
x = FibHeapLink(x, y);
146+
}
147+
A.RBInsert(FNodeDeg<T>(x));
148+
}
149+
for (auto i = A.TreeMinimum(); i != A.nil; i = A.TreeSuccessor(i)) {
150+
FNode<T>* x = i->data.data.data;
151+
DLLInsert(min, x);
152+
if (x->key < min->key)
153+
min = x;
154+
}
155+
}
156+
FNode<T>* FibHeapExtractMin() {
157+
FNode<T>* z = min;
158+
if (z) {
159+
while(z->child)
160+
DLLInsert(min, DLLRemove(z->child, z->child));
161+
DLLRemove(min, z);
162+
if (min)
163+
Consolidate();
164+
n--;
165+
}
166+
return z;
167+
}
168+
void print_tree(FNode<T>* x, size_t indent) {
169+
if (!x) {
170+
std::cout << std::endl;
171+
return;
172+
}
173+
std::cout << x->key << '\t';
174+
print_tree(x->child, indent + 1);
175+
for (FNode<T>* i = x->right; i != x; i = i->right) {
176+
std::cout << std::string(indent, '\t') << i->key << '\t';
177+
print_tree(i->child, indent + 1);
178+
}
179+
}
180+
void print_tree() {
181+
std::cout << std::endl;
182+
if (min)
183+
print_tree(min, 0);
184+
else
185+
std::cout << "(empty)" << std::endl;
186+
std::cout << std::endl;
187+
}
188+
~FibHeap() {
189+
while (min)
190+
delete DLLRemove(min, min)->recursive_destruct();
191+
}
90192
FNode<T>* min;
91193
size_t n;
92194
};
@@ -100,7 +202,8 @@ int main(int argc, char *argv[]) {
100202
std::cout << "i: insert" << std::endl;
101203
std::cout << "m: minimum" << std::endl;
102204
std::cout << "u: union" << std::endl;
103-
// std::cout << "p: print tree" << std::endl;
205+
std::cout << "e: extract minimum" << std::endl;
206+
std::cout << "p: print tree" << std::endl;
104207
std::cout << "q: quit" << std::endl;
105208
FNode<int>* ptr = nullptr;
106209
size_t n = 0;
@@ -135,6 +238,18 @@ int main(int argc, char *argv[]) {
135238
std::cin >> n2;
136239
*FH = FH->FibHeapUnion(FH_list[n2]);
137240
break;
241+
case 'e':
242+
ptr = FH->FibHeapExtractMin();
243+
if (ptr) {
244+
std::cout << "min = " << ptr->key << std::endl;
245+
delete ptr;
246+
ptr = FH->min;
247+
} else
248+
std::cout << "empty heap" << std::endl;
249+
break;
250+
case 'p':
251+
FH->print_tree();
252+
break;
138253
case 'q':
139254
return 0;
140255
}

README.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,3 +118,6 @@
118118
| 19 | FibHeap.cpp | Fib Heap Insert | 510 |
119119
| 19 | FibHeap.cpp | Fib Heap Minimum | 511 |
120120
| 19 | FibHeap.cpp | Fib Heap Union | 512 |
121+
| 19 | FibHeap.cpp | Fib Heap Extract Min | 513 |
122+
| 19 | FibHeap.cpp | Consolidate | 516 |
123+
| 19 | FibHeap.cpp | Fib Heap Link | 516 |

0 commit comments

Comments
 (0)