Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012 #include <shogun/lib/FibonacciHeap.h>
00013
00014 using namespace shogun;
00015
00016 CFibonacciHeap::CFibonacciHeap()
00017 {
00018 min_root = NULL;
00019
00020 max_num_nodes = 0;
00021 nodes = NULL;
00022 Dn = 0;
00023
00024 num_nodes = 0;
00025 num_trees = 0;
00026 }
00027
00028 CFibonacciHeap::CFibonacciHeap(int32_t capacity)
00029 {
00030 min_root = NULL;
00031
00032 max_num_nodes = capacity;
00033 nodes = SG_MALLOC(FibonacciHeapNode* , max_num_nodes);
00034 for(int32_t i = 0; i < max_num_nodes; i++)
00035 {
00036 nodes[i] = new FibonacciHeapNode;
00037 clear_node(i);
00038 }
00039
00040 Dn = 1 + (int32_t)(CMath::log2(max_num_nodes));
00041 A = SG_MALLOC(FibonacciHeapNode* , Dn);
00042 for(int32_t i = 0; i < Dn; i++)
00043 {
00044 A[i] = NULL;
00045 }
00046
00047 num_nodes = 0;
00048 num_trees = 0;
00049 }
00050
00051 CFibonacciHeap::~CFibonacciHeap()
00052 {
00053 for(int32_t i = 0; i < max_num_nodes; i++)
00054 {
00055 if(nodes[i] != NULL)
00056 delete nodes[i];
00057 }
00058 SG_FREE(nodes);
00059 }
00060
00061 void CFibonacciHeap::insert(int32_t index, float64_t key)
00062 {
00063 if(index >= max_num_nodes || index < 0)
00064 return;
00065
00066 if(nodes[index]->index != -1)
00067 return;
00068
00069
00070 nodes[index]->child = NULL;
00071 nodes[index]->parent = NULL;
00072
00073 nodes[index]->rank = 0;
00074 nodes[index]->index = index;
00075 nodes[index]->key = key;
00076 nodes[index]->marked = false;
00077
00078 add_to_roots(nodes[index]);
00079 num_nodes++;
00080 }
00081
00082 int32_t CFibonacciHeap::extract_min(float64_t &ret_key)
00083 {
00084 FibonacciHeapNode *min_node;
00085 FibonacciHeapNode *child, *next_child;
00086
00087 int32_t result;
00088
00089 if(num_nodes == 0)
00090 return -1;
00091
00092 min_node = min_root;
00093 if(min_node == NULL)
00094 return -1;
00095
00096 child = min_node->child;
00097 while(child != NULL && child->parent != NULL)
00098 {
00099 next_child = child->right;
00100
00101
00102 child->left->right = child->right;
00103 child->right->left = child->left;
00104
00105 add_to_roots(child);
00106
00107
00108 child = next_child;
00109 }
00110
00111
00112 min_node->left->right = min_node->right;
00113 min_node->right->left = min_node->left;
00114
00115 num_trees--;
00116
00117 if(min_node == min_node->right)
00118 {
00119 min_root = NULL;
00120 }
00121 else
00122 {
00123 min_root = min_node->right;
00124 consolidate();
00125 }
00126
00127 result = min_node->index;
00128 ret_key = min_node->key;
00129 clear_node(result);
00130
00131 num_nodes--;
00132
00133 return result;
00134 }
00135
00136 void CFibonacciHeap::clear()
00137 {
00138 min_root = NULL;
00139
00140
00141 for(int32_t i = 0; i < max_num_nodes; i++)
00142 {
00143 clear_node(i);
00144 }
00145
00146 num_nodes = 0;
00147 num_trees = 0;
00148 }
00149
00150 int32_t CFibonacciHeap::get_key(int32_t index, float64_t &ret_key)
00151 {
00152 if(index >= max_num_nodes || index < 0)
00153 return -1;
00154 if(nodes[index]->index == -1)
00155 return -1;
00156
00157 int32_t result = nodes[index]->index;
00158 ret_key = nodes[index]->key;
00159
00160 return result;
00161 }
00162
00163 void CFibonacciHeap::decrease_key(int32_t index, float64_t key)
00164 {
00165 FibonacciHeapNode* parent;
00166
00167 if(index >= max_num_nodes || index < 0)
00168 return;
00169 if(nodes[index]->index == -1)
00170 return;
00171 if(key > nodes[index]->key)
00172 return;
00173
00174
00175 nodes[index]->key = key;
00176
00177 parent = nodes[index]->parent;
00178
00179 if(parent != NULL && nodes[index]->key < parent->key)
00180 {
00181 cut(nodes[index], parent);
00182 cascading_cut(parent);
00183 }
00184
00185 if(nodes[index]->key < min_root->key)
00186 min_root = nodes[index];
00187 }
00188
00189
00190 void CFibonacciHeap::add_to_roots(FibonacciHeapNode *up_node)
00191 {
00192 if(min_root == NULL)
00193 {
00194
00195 min_root = up_node;
00196
00197 up_node->left = up_node;
00198 up_node->right = up_node;
00199 }
00200 else
00201 {
00202
00203 up_node->right = min_root->right;
00204 up_node->left = min_root;
00205
00206 up_node->left->right = up_node;
00207 up_node->right->left = up_node;
00208
00209
00210 if(up_node->key < min_root->key)
00211 {
00212 min_root = up_node;
00213 }
00214 }
00215
00216 up_node->parent = NULL;
00217 num_trees++;
00218 }
00219
00220 void CFibonacciHeap::consolidate()
00221 {
00222 FibonacciHeapNode *x, *y, *w;
00223 int32_t d;
00224
00225 for(int32_t i = 0; i < Dn; i++)
00226 {
00227 A[i] = NULL;
00228 }
00229
00230 min_root->left->right = NULL;
00231 min_root->left = NULL;
00232 w = min_root;
00233
00234 do
00235 {
00236 x = w;
00237 d = x->rank;
00238 w = w->right;
00239
00240 while(A[d] != NULL)
00241 {
00242 y = A[d];
00243
00244 if(y->key < x->key)
00245 {
00246 FibonacciHeapNode *temp;
00247
00248 temp = y;
00249 y = x;
00250 x = temp;
00251 }
00252
00253 link_nodes(y, x);
00254
00255 A[d] = NULL;
00256 d++;
00257 }
00258 A[d] = x;
00259 }
00260 while(w != NULL);
00261
00262 min_root = NULL;
00263 num_trees = 0;
00264
00265 for(int32_t i = 0; i < Dn; i++)
00266 {
00267 if(A[i] != NULL)
00268 {
00269 A[i]->marked = false;
00270 add_to_roots(A[i]);
00271 }
00272 }
00273 }
00274
00275 void CFibonacciHeap::link_nodes(FibonacciHeapNode *y, FibonacciHeapNode *x)
00276 {
00277 if(y->right != NULL)
00278 y->right->left = y->left;
00279 if(y->left != NULL)
00280 y->left->right = y->right;
00281
00282 num_trees--;
00283
00284 y->left = y;
00285 y->right = y;
00286
00287 y->parent = x;
00288
00289 if(x->child == NULL)
00290 {
00291 x->child = y;
00292 }
00293 else
00294 {
00295 y->left = x->child;
00296 y->right = x->child->right;
00297
00298 x->child->right = y;
00299 y->right->left = y;
00300 }
00301
00302 x->rank++;
00303
00304 y->marked = false;
00305 }
00306
00307 void CFibonacciHeap::clear_node(int32_t index)
00308 {
00309 nodes[index]->parent = NULL;
00310 nodes[index]->child = NULL;
00311 nodes[index]->left = NULL;
00312 nodes[index]->right = NULL;
00313
00314 nodes[index]->rank = 0;
00315 nodes[index]->index = -1;
00316 nodes[index]->key = 0;
00317
00318 nodes[index]->marked = false;
00319 }
00320
00321 void CFibonacciHeap::cut(FibonacciHeapNode *child, FibonacciHeapNode *parent)
00322 {
00323 if(parent->child == child)
00324 parent->child = child->right;
00325
00326 if(parent->child == child)
00327 parent->child = NULL;
00328
00329 parent->rank--;
00330
00331 child->left->right = child->right;
00332 child->right->left = child->left;
00333 child->marked = false;
00334
00335 add_to_roots(child);
00336 }
00337
00338 void CFibonacciHeap::cascading_cut(FibonacciHeapNode *tree)
00339 {
00340 FibonacciHeapNode *temp;
00341
00342 temp = tree->parent;
00343 if(temp != NULL)
00344 {
00345 if(!tree->marked)
00346 {
00347 tree->marked = true;
00348 }
00349 else
00350 {
00351 cut(tree, temp);
00352 cascading_cut(temp);
00353 }
00354 }
00355 }
00356
00357 void CFibonacciHeap::debug_print()
00358 {
00359 SG_SPRINT("%d %d\n", num_trees, num_nodes);
00360 for(int32_t i = 0; i < max_num_nodes; i++)
00361 {
00362 if(nodes[i]->index == -1)
00363 {
00364 SG_SPRINT("None\n");
00365 }
00366 else
00367 {
00368 SG_SPRINT("%f\n",nodes[i]->key);
00369 }
00370 }
00371 }