Fibonacci Heap实现

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

先贴代码:

#include
#include
#include
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->keykey)
				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->keykey)
	{
		cut(nd);
		cascadingCut(p);
	}
	if(nd->keykey)
	{
		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;iheight]=min;
	nd=min->right;
	while(nd!=min)
	{
		tmp=nd;
		height=tmp->height;
		while(arr[height]!=NULL&&arr[height]!=nd)
		{
			if(arr[height]->keykey)
				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->keymin->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也快不了多少...

你可能感兴趣的:(算法码源,日经,类库,排序算法)