Fibonacci Heap实现

来源:互联网 发布:wifi局域网劫持软件 编辑:程序博客网 时间:2024/04/30 13:56

本算法是对<算法导论>相关章节伪代码的实现:

先贴代码:

#include<iostream>#include<fstream>#include<cstdlib>using namespace std;class FibonacciHeap;class node{friend class FibonacciHeap;node(int v):key(v),height(0),parent(NULL),left(this),right(this),child(NULL),mark(false){}int key;int height;node* parent;node* left;node* right;node* child;bool mark;};class FibonacciHeap{friend ostream& operator<<(ostream&,node*);public:FibonacciHeap():min(NULL),total(0){};~FibonacciHeap();node* minimum();void extractMin();void insert(int);void deleteNode(node*);void decreaseNode(node*,int);bool empty();private:node* min;node* arr[1000000];int total;void removeChild(node*);void consolidate();void cut(node*);void cascadingCut(node*);FibonacciHeap* unionHeap(FibonacciHeap*,FibonacciHeap*);void linkNode(node*,node*);};FibonacciHeap::~FibonacciHeap(){while(min){extractMin();}for(int i=0;i<1000000;++i){delete arr[i];arr[i]=NULL;}}node* FibonacciHeap::minimum(){return min;}void FibonacciHeap::extractMin(){if(min==NULL)exit(0);node *tmp=NULL,*tmpmin=NULL;while(min->child!=NULL){removeChild(min->child);}if(min->right==min){delete min;min=NULL;}else{tmpmin=min;min=NULL;tmp=tmpmin->right;while(tmp!=tmpmin){if(min==NULL||tmp->key<min->key)min=tmp;tmp=tmp->right;}tmpmin->right->left=tmpmin->left;tmpmin->left->right=tmpmin->right;delete tmpmin;tmpmin=NULL;tmp=NULL;}if(--total>0)consolidate();}void FibonacciHeap::insert(int data){node* nd=new node(data);nd->left=nd;nd->right=nd;FibonacciHeap* addheap=new FibonacciHeap();addheap->min=nd;addheap->total=1;addheap=unionHeap(this,addheap);this->min=addheap->min;this->total=addheap->total;addheap=NULL;}void FibonacciHeap::deleteNode(node* nd){nd->key=-32767;extractMin();}void FibonacciHeap::decreaseNode(node* nd,int data){nd->key=data;node* p=nd->parent;if(p!=NULL&&nd->key<p->key){cut(nd);cascadingCut(p);}if(nd->key<min->key){min=nd;}}void FibonacciHeap::removeChild(node* nd){if(nd->right==nd){nd->parent->child=NULL;}else{nd->right->left=nd->left;nd->left->right=nd->right;if(nd==nd->parent->child)nd->parent->child=nd->right;}nd->right=nd->parent->right;nd->parent->right->left=nd;nd->left=nd->parent;nd->parent->right=nd;nd->parent=NULL;nd->mark=false;}void FibonacciHeap::consolidate(){node *nd,*tmp;int height;for(int i=0;i<total;++i)arr[i]=NULL;arr[min->height]=min;nd=min->right;while(nd!=min){tmp=nd;height=tmp->height;while(arr[height]!=NULL&&arr[height]!=nd){if(arr[height]->key<tmp->key)swap(arr[height],tmp);linkNode(tmp,arr[height]);arr[height]=NULL;height=tmp->height;}arr[height]=tmp;nd=tmp->right;}}void FibonacciHeap::cut(node *curnode){removeChild(curnode);curnode->mark=false;}void FibonacciHeap::cascadingCut(node *pnode){node* p=pnode->parent;if(p!=NULL){if(pnode->mark==false)pnode->mark=true;else{cut(pnode);cascadingCut(p);}}}FibonacciHeap* FibonacciHeap::unionHeap(FibonacciHeap* hp1,FibonacciHeap* hp2){FibonacciHeap* newHeap=new FibonacciHeap();newHeap->min=(hp1->min!=NULL)?hp1->min:hp2->min;if(newHeap->min!=hp2->min){newHeap->min->right->left=hp2->min->left;hp2->min->left->right=newHeap->min->right;hp2->min->left=newHeap->min;newHeap->min->right=hp2->min;if(hp2->min->key<newHeap->min->key)newHeap->min=hp2->min;}newHeap->total=hp1->total+hp2->total;hp1->min=NULL;hp2->min=NULL;return newHeap;}void FibonacciHeap::linkNode(node *tarNode,node *obNode){obNode->left->right=obNode->right;obNode->right->left=obNode->left;if(tarNode->child!=NULL){obNode->left=tarNode->child->left;tarNode->child->left->right=obNode;obNode->right=tarNode->child;tarNode->child->left=obNode;}else{obNode->left=obNode;obNode->right=obNode;}obNode->parent=tarNode;tarNode->child=obNode;++tarNode->height;}bool FibonacciHeap::empty(){return min==NULL;}

算法导论上讲的很明白了.

比较FibonacciHeap和BinomialHeap,为什么FibonacciHeap不在插入的时候对根节点进行合并呢?因为FibonacciHeap是最小有限数列,它的最主要功能是void minimum()和void extractMin(),其他功能都是附属功能,既然(node*)min已经指向的最小节点,所以就没有必要在insert的时候合并以保持FibonacciHeap的结构特点了.况且在定义中我们可以看出FibonacciHeap对结构的要求不想BinomialHeap那么高,所以从定义上讲也没有必要合并.更重要的是,在extractMin()操作的时候还会剪枝,如果在插入的时候就进行合并的话,反而在extractMin的时候还会加上removeChild(node*)和consolidate()的操作,多此一举了.所以,FibonacciHeap和binomialHeap的最大不同之处是FibonacciHeap放弃了结构上的一致性,以换取更快的处理速度.这一点在进行decrease(node*,int)的时候特别明显.

在进行decrease(node*,int)的时候为什么要进行cut(node*)和cascadingCut(node*)呢?出于结构一致性的考量,应该进行如下操作:

node* pnode=nd->parent;

while(pnode->key>key)

{

swap(nd->key,pnode->key);

nd=pnode;

pnode=nd->parent;

}

才对,为什么要剪枝呢?因为FibonacciHeap最主要的功能是minimum()和extractMin(),反正在进行extractMin()的时候还要剪枝,往上遍历了后来还要减去,出于速度上的考量,干脆一开始就把它减去.而且往上遍历不知道要遍历多少个,直接把剪去更加省事.

FibonacciHeap性能上有多强劲现在我还感受不出来,因为没有那么多数据...现在感觉比BinomialHeap也快不了多少...

0 0