#include #include #include /** * Heap operation are defined with node pointer to allow * decrease key to be called with the given node. */ struct Node { int key; int degree; bool mark; int data; // an extra field, not required for implementation Node* left; Node* right; Node* parent; Node* child; Node(int key): key(key){}; Node(int key, int data): key(key), data(data){}; friend std::ostream& operator<<(std::ostream& os, const Node &n){ os << "{ " << "key: " << n.key << " ; " << "degree: " << n.degree << "; " << "mark: " << n.mark << "; " << "data: " << n.data << "; " << "left: " << (n.left == nullptr? -1: n.left->data) << "; " << "right: " << (n.right == nullptr? -1: n.right->data) << "; " << "parent: " << (n.parent == nullptr? -1: n.parent->data) << "; " << "child: " << (n.child == nullptr? -1: n.child->data) << "; " << " }"; return os; } }; class FibonacciHeap { private: Node* _mn; int _length; /** * @brief inserts a node to rootlist after given node * * @param after * @param toInsert */ void _insertTORootListAfterNode(Node *after, Node *toInsert){ if(after->right == after){ //after ----> after toInsert toInsert->right = toInsert->left = after; after->right = after->left = toInsert; return ; } // after next // after toInsert next toInsert->left = after; toInsert->right = after->right; toInsert->left->right = toInsert; toInsert->right->left = toInsert; } /** * @brief removes the given node from rootlist * but it still contains reference to its neighbours * * @param toDelete * @return Node* */ Node* _removeNodeFromRootList(Node *toDelete){ auto left = toDelete->left; if(toDelete == left) // only one child left left = nullptr; else if(toDelete->right == toDelete->left){ // only two child left // cld left ---> left left->left = left; left->right = left; } else{ // if at least three child is there // left cld right // left right toDelete->left->right = toDelete->right; toDelete->right->left = toDelete->left; } toDelete->parent = nullptr; return left; } /** * @brief inserts all child node of parent node to same rootlist * the parent exists * * @param parent */ void _insertChildOfNodeToRootList(Node* parent){ for(auto cld = parent->child; cld != nullptr;){ auto left = _removeNodeFromRootList(cld); _insertTORootListAfterNode(parent, cld); cld = left; } } /** * @brief inserts a new child at root list after insertAt * * @param insertAt * @param toInsert * @return Node* insertAt node is changed in the function call * so it is recommanded to assign to the return value; */ Node* _insertNewChildAtRootList(Node* insertAt, Node* toInsert){ if(insertAt == nullptr){ insertAt = toInsert; insertAt->right = toInsert; insertAt->left = toInsert; } else{ _insertTORootListAfterNode(insertAt, toInsert); } return insertAt; } /** * @brief links child a children of parent and performs * associated links * * @param parent * @param child * @return Node* */ Node* _fibHeapLink(Node* parent, Node* child){ _removeNodeFromRootList(child); child->parent = parent; parent->child = _insertNewChildAtRootList(parent->child, child); child->mark = false; parent->degree ++; return parent; } /** * @brief consolidates the fibonacchi heap * */ void _consolidate(){ std::vector roots; roots.push_back(_mn); for(auto cur = _mn->right; cur != _mn ;cur = cur->right){ roots.push_back(cur); } int upper_bound = log2(_length) + 2; std::vector array(upper_bound, nullptr); for(auto cur : roots){ auto z = cur; int d = cur->degree; while(array[d] != nullptr){ auto y = array[d]; if(z->key <= y->key) z = _fibHeapLink(z, y); else z = _fibHeapLink(y, z); array[d] = nullptr; d++; } array[d] = z; } _mn = nullptr; for(auto node: array){ if(node == nullptr) continue; _mn = _insertNewChildAtRootList(_mn, node); if(_mn->key > node->key){ _mn = node; } } } void _cut(Node* parent, Node* node){ parent->child = _removeNodeFromRootList(node); if(parent->child) parent->child->parent = parent; parent->degree--; _insertTORootListAfterNode(_mn, node); node->parent = nullptr; node->mark = false; } void _cascadingCut(Node* parent){ auto grandP = parent->parent; if(grandP != nullptr){ if(parent->mark == false) parent->mark = true; else { _cut(grandP, parent); _cascadingCut(grandP); } } } void _printHelper(std::ostream& os, Node *n, int tab){ if(n == nullptr) return ; for(int i = 0; i < tab; i++) os << "\t"; os << *n << std::endl; _printHelper(os, n->child, tab+1); for(auto cur = n->right; cur != n; cur = cur->right){ for(int i = 0; i < tab; i++) os << "\t"; os << *cur << std::endl; _printHelper(os, cur->child, tab+1); } } public: FibonacciHeap(/* args */); ~FibonacciHeap(); void insert(Node *toInsert){ toInsert->degree = 0; toInsert->mark = false; toInsert->parent = nullptr; toInsert->child = nullptr; _mn = _insertNewChildAtRootList(_mn, toInsert); if(_mn->key > toInsert->key){ _mn = toInsert; } _length++; } void pop(){ if(_mn != nullptr){ _insertChildOfNodeToRootList(_mn); _removeNodeFromRootList(_mn); if(_mn->left == _mn){ _mn = nullptr; }else{ _mn = _mn->right; _consolidate(); } _length--; } } Node* top(){ return _mn; } int length(){ return _length; } void decreaseKey(Node* node, int k){ if(node->key <= k) { std::cerr << "node->key <= k" << std::endl;; return ; } node->key = k; auto parent = node->parent; if(parent != nullptr && node->key < parent->key){ _cut(parent, node); _cascadingCut(parent); } if(node->key < _mn->key){ _mn = node; } } friend std::ostream& operator<<(std::ostream& os, FibonacciHeap &f){ os << "====================================================" << std::endl; if(f._mn == nullptr) os << "null" << std::endl; os << "length : " << f._length << std::endl; f._printHelper(os, f._mn, 0); os << "====================================================" << std::endl; return os; } }; FibonacciHeap::FibonacciHeap(/* args */) { _mn = nullptr; _length = 0; } FibonacciHeap::~FibonacciHeap() { } int main(int argc, char const *argv[]) { FibonacciHeap fh; Node *node1 = new Node(10, 5); Node *node2 = new Node(20, 5); Node *node3 = new Node(30, 5); fh.insert(node1); fh.insert(node2); fh.insert(node3); std::cout << fh << std::endl; std::cout << "Top : " << *fh.top() << std::endl; fh.decreaseKey(node3, 5); std::cout << fh << std::endl; std::cout << "Top : " << *fh.top() << std::endl; fh.pop(); std::cout << fh << std::endl; std::cout << "Top : " << *fh.top() << std::endl; fh.pop(); fh.pop(); std::cout << fh << std::endl; delete node1; delete node2; delete node3; }