binomial heap实现

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

下面贴代码:

#include<iostream>
#include<cstdlib>
using namespace std;

struct node
{
	node(int d):data(d),degree(0),parent(NULL),child(NULL),sibling(NULL){}
	int data;
	int degree;
	node* parent;
	node* child;
	node* sibling;
};

class BinomialHeap
{
public:
	BinomialHeap():head(NULL){}
	~BinomialHeap(){ClearHeap(head);};
	node* Minimum();
	void ExtractMin();
	void Union(BinomialHeap*,BinomialHeap*);
	void Insert(int);
	node* GetHead();
	void SetHead(node*);
	bool Empty();
private:
	node* head;
	void UnionNode(node*,node*);
	node* MergeBinomialHeap(BinomialHeap*,BinomialHeap*);
	void ClearHeap(node*);
	node* Reverse(node*);
};

node* BinomialHeap::Minimum()
{
	node *nd=head,*min=head;
	while(nd!=NULL)
	{
		if(nd->data<min->data)
			min=nd;
		nd=nd->sibling;
	}
	return min;
}

void BinomialHeap::ExtractMin()
{
	if(head!=NULL)
	{
		node *nd=head,*n=head;
		while(nd!=NULL)
		{
			if(nd->data<n->data)
				n=nd;
			nd=nd->sibling;
		}
		nd=head;
		while(nd->sibling!=n&&nd->sibling!=NULL)
			nd=nd->sibling;
		nd->sibling=n->sibling;
		BinomialHeap* tmpheap=new BinomialHeap();
		nd=n->child;
		while(nd!=NULL&&nd->sibling!=NULL)
			nd=nd->sibling;
		tmpheap->SetHead(nd);
		Reverse(n->child);
		if(n==head)
		{
			head=NULL;
		}
		delete n;
		n=NULL;
		Union(this,tmpheap);
	}
}

void BinomialHeap::Union(BinomialHeap *h1,BinomialHeap *h2)
{
	node* nd=MergeBinomialHeap(h1,h2);
	if(nd==NULL)
	{
		head=NULL;
		exit(0);
	}
	node* x=nd;
	node* pre=NULL;
	node* sib;
	while(x!=NULL&&x->sibling!=NULL)
	{
		sib=x->sibling;
		if((x->degree!=sib->degree)||(sib->sibling!=NULL&&x->degree==sib->sibling->degree))
		{
			pre=x;
			x=x->sibling;
		}
		else
		{
			if(x->data<=sib->data)
			{
				x->sibling=sib->sibling;
				UnionNode(sib,x);
			}
			else
			{
				if(pre==NULL)
				{
					nd=sib;
				}
				else
				{
					pre->sibling=sib;
				}
				UnionNode(x,sib);
				x=sib;
			}
		}
		if(x==NULL)
			break;
		
	}
	head=nd;
}


void BinomialHeap::Insert(int data)
{
	BinomialHeap* tmpHeap=new BinomialHeap();
	node* nd=new node(data);
	tmpHeap->SetHead(nd);
	Union(this,tmpHeap);
}

node* BinomialHeap::GetHead()
{
	return head;
}

void BinomialHeap::SetHead(node* nd)
{
	head=nd;
}

bool BinomialHeap::Empty()
{
	return head==NULL;
}

void BinomialHeap::UnionNode(node *nd1,node *nd2)
{
	nd1->parent=nd2;
	nd1->sibling=nd2->child;
	nd2->child=nd1;
	nd2->degree+=1;
}

node* BinomialHeap::Reverse(node* nd)
{
	if(nd!=NULL)
	{
		if(nd->sibling!=NULL)
		{
			Reverse(nd->sibling)->sibling=nd;
		}
		nd->sibling=NULL;
		return nd;
	}
}

node* BinomialHeap::MergeBinomialHeap(BinomialHeap* h1,BinomialHeap* h2)
{
	node *nd,*sib,*nd1,*nd2;
	nd1=h1->GetHead();
	nd2=h2->GetHead();
	h1->SetHead(NULL);
	h2->SetHead(NULL);
	if(nd1==NULL||nd2==NULL)
	{
		nd=(nd1==NULL?nd2:nd1);
		return nd;
	}
	if(nd1->degree<nd2->degree)
	{
		nd=nd1;
		nd1=nd1->sibling;
	}
	else
	{
		nd=nd2;
		nd2=nd2->sibling;
	}
	sib=nd;
	while(nd1!=NULL&&nd2!=NULL)
	{
		if(nd1->degree<nd2->degree)
		{
			sib->sibling=nd1;
			nd1=nd1->sibling;
		}
		else
		{
			sib->sibling=nd2;
			nd2=nd2->sibling;
		}
		sib=sib->sibling;
	}
	if(nd1!=NULL)
	{
		sib->sibling=nd1;
	}
	if(nd2!=NULL)
	{
		sib->sibling=nd2;
	}
	return nd;
}

void BinomialHeap::ClearHeap(node* nd)
{
	if(nd!=NULL)
	{
		ClearHeap(nd->sibling);
		ClearHeap(nd->child);
		delete nd;
		nd=NULL;
	}
}

本算法的核心就是Union(BinomialHeap*,BinomialHeap*)算法,而Union算法的核心就是一句话:

    For any nonnegative interger k,there is at most one binomial tree in H whose root has degree k.

Union算法是怎么实现的呢?算法导论把Union的过程分成了四种情况:

1.degree[x]<degree[next-x]

2.degree[x]==degree[next-x]==degree[next[next-x]].

3.degree[x]=degree[next-x]&&key[x]<=key[next-x]

4.degree[x]=degree[next-x]&&key[x]>key[next-x]

第一种情况是很好理解的(要先理解MergeBinomialHeap的过程以及binomial heap的结构),因为degree[x]<degree[next-x]满足binomial heap的结构,所以直接pass

第三种和第四种情况也是很好理解的(先理解binomial tree的机理),两个高度相同的,直接合并就好了.

第二种情况有点问题,为什么会出现连续三个高度相同的binomial tree呢,在binomial heap中不是每棵树的高度都不一样吗.....k,k,.....这种情况是比较正常和好理解的.....k,k,k,....结构是怎么出来的呢?原因就是....k,k,k+1,k+1,....,在对前两个高度为k的binomial tree进行合并之后,就出现了,...k+1,k+1,k+1,....,为什么三个连续的要跳过第一个呢,因为对第一个合并之后得到...k+2,k+1,...违反了binomial heap的结构,所以不能合并.

所以,要先理解binomial tree的结构,后理解binomial heap的结构,接下来的就水到渠成,该怎么写就怎么写了.


=========发什么疯,害我重写一遍=========

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值