Fibonacci堆的代码-欢迎斧正并且报告Bug

来源:互联网 发布:particle fever 知乎 编辑:程序博客网 时间:2024/04/30 06:02
#include"stdafx.h"#include<math.h>#include<stdio.h>#include"PriorityQueue.h"#include<iostream>#include<set>#include<vector>using namespace std;//Node:   //Pointer: Left, Right, Parent, Child   //bool mark, ElemType elem, int degreeclass Node {public:Node();Node(ElemType elem);Node *left, *right, *parent, *child;bool mark;ElemType elem;int degree;};//FibonacciHeap  //Size  //Pointer: rootlist, minclass FibHeap {public:FibHeap();void Insert(ElemType elem);void Insert(Node *t);Node* ExtractMin();void DecreaseKey(Node *e, int key);void FibHeapDelete(Node *e);set<Node*> FibHeapNodes;vector<Node *>FibHeapNodesVector; //For delete~FibHeap();protected:void Consolidate();void Cut(Node *cutnode, Node *parent);void CascadingCut(Node *node);int MaxDegree(); //Return the max degree of node in the FibHeapvoid FibLink(Node *y, Node *x);private:Node* rootlist;Node* min;int size;};void TestFib();int main() {//freopen("input.txt", "r", stdin);TestFib();int i = 0; cin>>i;}/* 1 2 1 3 1 4 1 5 2  2 2 */void TestFib() {FibHeap *fib = new FibHeap();int i;ElemType elem;Node *ret = 0;set<Node *>::reverse_iterator it;while(true) {cin>>i;switch(i) {case 1://Insertcin>>elem.key;fib->Insert(elem);break;case 2://ExtractMinret = fib->ExtractMin();if(ret == 0) cout<<"error"<<endl;else cout<<ret->elem.key<<endl;break;case 3:for(it = fib->FibHeapNodes.rbegin(); it != fib->FibHeapNodes.rend(); it++) {fib->DecreaseKey(*it, (*it)->elem.key - 1);}break;case 4:break;case 5:delete fib;return;}}}Node::Node() { //这段重复代码如何去除left = right = parent = child = 0;mark = false;degree = 0;}Node::Node(ElemType elem) {this->elem = elem;left = right = parent = child = 0;mark = false;degree = 0;}FibHeap::FibHeap(){this->min = this->rootlist = 0;this->size = 0;}void FibHeap::Insert(ElemType elem) {Node *e = new Node(elem);Insert(e);}void FibHeap::Insert(Node *t) {FibHeapNodes.insert(t);t->left = t->right = t;if(rootlist == 0) {this->min = this->rootlist = t;} else{t->right = rootlist;t->left = rootlist->left;t->left->right = t->right->left = t;if(Less(t->elem, this->min->elem)) this->min = t;}this->size++;}Node *FibHeap::ExtractMin() {Node* ret = this->min;//Add all the child of this->min to the rootlist of Heapif(ret == 0) return 0;if(ret->child != 0) {//Add all the child of this->min to the rootlist//at this time, rootlist != NIL<Because of the existence of ret>Node *prev = ret->child, *next;do {//Add the node of prev to the rootlistnext = prev->right;prev->right = rootlist;prev->left = rootlist->left;prev->left->right = prev->right->left = prev;rootlist = prev; //rootlist可改可不改prev->parent = 0;prev = next;} while(next != ret->child);}//Remove this->minret->right->left = ret->left;ret->left->right = ret->right;if(rootlist == ret) rootlist = ret->right;if(ret == ret->right)this->rootlist =  this->min = 0;else {this->min = ret->right;Consolidate();}//Consolidate the FibHeapthis->size--;FibHeapNodes.erase(ret);return ret;}void FibHeap::Consolidate() {int maxDegree = this->MaxDegree();//数组一定要初始化Node **aux = new Node* [maxDegree + 1]; //Auxiliary Array< aux[d]: tree with degree d>for(int i = 0; i <= maxDegree; i++) aux[i] = 0;//Iterate over the rootlistNode *iter = rootlist, *next;if(iter == 0) return;//It means the list is emptydo {Node *x = iter; //FibLink Will change Iterint degree = x->degree;next = iter->right;while(aux[degree] != 0) {Node *y = aux[degree];if(Less(y->elem, x->elem)) {//SWAP X AND Y 可以考虑用宏实现Node *temp = x;x = y; y = temp;}FibLink(y, x); //Let y be a child of x //此处改变了next->rightaux[degree] = 0;degree++;}aux[degree] = x;iter = next; //iter can't be zero}while(iter != rootlist);//Reconstruct the listthis->min = this->rootlist = 0;for(int i = 0; i <= maxDegree; i++) { //Add the list to the rootlistif(aux[i] != 0) { //代码可以更加简洁if(rootlist == 0){this->min = this->rootlist = aux[i]->left = aux[i]->right = aux[i]; // When rootlist is empty}else {//Add aux[i];aux[i]->right = rootlist;aux[i]->left = rootlist->left;aux[i]->left->right = aux[i]->right->left = aux[i];if(Less(aux[i]->elem, this->min->elem)) this->min = aux[i];}}}delete[] aux;}void FibHeap::FibLink(Node *y, Node *x) {//Remove y from the rootlist, may no need 这一个决定删去,因为会影响正确性//y->left->right = y->right;//这一段话导致了next值出错 if y is the rootlist//y->right->left =  y->left;//if(y == rootlist) rootlist = y->right; 加上这一句话也未必是对的//Make y a child of x, add the degree of x 双向链表的表头。 对指针的引用存在不?y->parent = x;if(x->child == 0) x->child = y->left = y->right = y;else {y->left = x->child->left;y->right = x->child;y->left->right = y->right->left = y;}x->degree++;//Mark y = false why? y的度已经改变了。然后重新加入到rootlist中的,所以mark可以为负值y->mark = false; }void FibHeap::DecreaseKey(Node *e, int key) {if(e == 0) return;if(e->elem.key <= key) return;e->elem.key = key;Node *p = e->parent;if(p != 0 && Less(e->elem, p->elem)) {Cut(e, p);CascadingCut(p);}if(Less(e->elem, this->min->elem)) this->min = e;}void FibHeap::Cut(Node *cutNode, Node *parent) { //Remove cutNode from parent listif(parent->child == cutNode) {if(parent->degree == 1) //Only one childparent->child = 0;elseparent->child = cutNode->right;}cutNode->right->left = cutNode->left;cutNode->left->right = cutNode->right;parent->degree--;//Add cutNode to the rootlist //rootlist can't be empty!cutNode->right = rootlist;cutNode->left = rootlist->left;cutNode->left->right = cutNode->right->left = cutNode;//Pointer:mark parentcutNode->mark = false; //?? why?? 还是无法理解mark商标cutNode->parent = 0;}void FibHeap::CascadingCut(Node *node) {Node *parent = node->parent;if(parent != 0) if(parent->mark == false) parent->mark = true;else{Cut(node, parent);CascadingCut(parent);}}void FibHeap::FibHeapDelete(Node *e) {this->DecreaseKey(e, -9999);free(this->ExtractMin());}int FibHeap::MaxDegree() {if(this->size == 0) return 0;int max = (int) (2 * log((float)this->size) / log((float)2)) + 2;return max;} FibHeap::~FibHeap() {set<Node*>::iterator it;for(it = FibHeapNodes.begin(); it != FibHeapNodes.end(); it++) FibHeapNodesVector.push_back(*it);for(int i = 0; i < FibHeapNodesVector.size(); i++) {cout<<"Clearing: "<<FibHeapNodesVector[i]->elem.key<<endl;FibHeapDelete(FibHeapNodesVector[i]);}}