FibonacciHeap.cpp

Go to the documentation of this file.
00001 /*
00002  * This program is free software; you can redistribute it and/or modify
00003  * it under the terms of the GNU General Public License as published by
00004  * the Free Software Foundation; either version 3 of the License, or
00005  * (at your option) any later version.
00006  *
00007  * Written (W) 2011 Evgeniy Andreev (gsomix)
00008  *
00009  * Copyright (C) 2011 Berlin Institute of Technology and Max-Planck-Society
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; // node is not empty
00068 
00069     // init "new" node in array
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; // heap is empty now
00095 
00096     child = min_node->child;
00097     while(child != NULL && child->parent != NULL)
00098     {
00099         next_child = child->right;
00100 
00101         // delete current child from childs list
00102         child->left->right = child->right;
00103         child->right->left = child->left;
00104 
00105         add_to_roots(child);
00106 
00107         // next iteration
00108         child = next_child;
00109     }
00110 
00111     // delete minimun from root list
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; // remove last element
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     // clear all nodes
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; // node is empty
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         // if heap is empty, node becomes circular root list
00195         min_root = up_node;
00196 
00197         up_node->left = up_node;
00198         up_node->right = up_node;
00199     }
00200     else
00201     {
00202         // insert node to root list
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         // nomination of new minimum node
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 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines

SHOGUN Machine Learning Toolbox - Documentation