非波拉基堆

代码还没写完,但是么得啥时间去修改,先把昨晚写的粘上来,过几天把万恶的啥完成了在来修改,备注一下。
#include <iostream>
#include <vector>
#define D 10 //D=lgn,n为该堆的节点个数
using namespace std;
//非波拉基堆的节点结构有点特殊它包含有:一个含有的键值,一个指向该节点父节点指针,一个指向任一子节点的指针,一个表示该节点度数
//一个指向该节点左和右的指针,以及一个mark,表示该节点自从上次成为某节点的子女后是否减少了一个子女。
class node
{
public://不考虑封装性
	int k;
	int degree;
	node* p;
	node* child;
	node* left;
	node* right;
	bool mark;
public:
	node(int key):k(key),degree(0),p(NULL),child(NULL),left(NULL),right(NULL),mark(false)//这里相当于初始化
	{}
};
//对于非波拉基堆的话就是存放n个节点以及一个指向根表的指针,指向的是根表中的最小关键字节点。
class fbheap
{
public:
	node* min;
	vector<node> fb;
	int nh;//指示根表中的个数
public:
	fbheap():min(NULL),nh(0){}
};



void insert(fbheap* pf,node* x)
{

	x->degree=0;
	x->p=NULL;
	x->child=NULL;
	x->left=x;
	x->right=x;
	x->mark=false;
	if(pf->nh==0)//空堆
	{
		pf->min=x;
		pf->fb.push_back(*x);
	}
	else//非空
	{
		x->right=pf->min->right;
		x->left=pf->min;
		pf->min->right->left=x;
		pf->min->right=x;
	}
	if(pf->min->k<x->k)
	{
		pf->min=x;
	}
	pf->nh=pf->nh+1;
}

void searchmin(fbheap* pf)
{
	cout<<"min is:"<<pf->min->k<<endl;
}

node* fbheapunion(fbheap* pf1,fbheap* pf2)
{
	fbheap* pf=new fbheap();//先建一个新堆,空的
//	p=pf1;
	pf->min=pf1->min;
//下面是把pf2堆指向的根表和pf1的相结合
	node* t1=pf1->min->right;
	node* t2=pf2->min->left;
	while (t1->right!=t1 &&t2->left!=t2 )
	{
		t1=t1->right;//pf向右,pf2向左
		t2=t2->left;
	}
	t1->right=t2;
	t2->left=t1;
	if (pf1->min==NULL||pf2->min->k<pf1->min->k)
	{
		pf->min=pf2->min;
	}
	pf->nh=pf1->nh+pf2->nh;

	return pf->min;
}

void fblink(fbheap* pf,node* y,node *x)//x,和y要都是在跟表上的
{
	y->left->right=y->right;
	y->right->left=y->left;
	//这里有一点要明确的就是原来的x的孩子是有的,所以原来的x的child指针是有指向的,那么现在要么把该child指针指向y,或者是不指向应该也不错吧?
	if(y==pf->min)
		pf->min=x;
	if(x->child==NULL)
	{
		y->left=y;
		y->right=y;
		x->child=y;
	}
	else 
	{
		x->child->left=y;
		y->left=x->child->left;
		y->right=x->child;
		x->child->left->right=y;//无论是含有x含有多少个孩子我们都把y放在x->child的左边
	}
	y->p=x;
	x->degree=x->degree+1;
	y->mark=false;
	
}

void consolidate(fbheap* pf)
//对于该次而言的话我们需要的是事先知道一个数组,数组之中存放的是个数是的最大度数的一个数组,数组中存放的指针
//A[i]=y的意思就是y的度数为i,由于一系列的操作是要求的根表的数。
{
	node* A[D];//D事先可以知道,且对于该数组中的指针实际上也是事先知道指向的元素的位置的。
	node* w;
	for(int i=0;i!=D;++i)
	{
		A[i]=NULL;
	}
	node* t=pf->min;
	while (t->left!=t)
	{
		t=t->left;
	}
	for(;t->right!=t;t=t->right)
	{
		node* x=t;
		int d=t->degree;
		while (A[d]!=NULL)//对于度数d还有其他的指针
		{
			node* y=A[d];
			if (y->k<x->k)
			{
				swap(x,y);
			}
			fblink(pf,y,x);
			A[d]=NULL;
			d=d+1;
		}
		A[d]=x;

	}
	pf->min=NULL;
	for(int i=0;i!=D;++i)
	{
		if(A[i]!=NULL)
		{
			pf->min->left=A[i];
			pf->min->left->right=A[i];
			A[i]->left=pf->min->left;
			A[i]->right=pf->min;
		}
		if (A[i]->k<pf->min->k||pf->min==NULL)
		{
			pf->min=A[i];
		}
	}
}

void extratemin(fbheap* pf)
{
	node* z=pf->min;
	if(z!=NULL)
	{
		node* tr=z->right;
		node* tl=z->left;
		for(;tr!=tl->left;tl=tl->left)
		{
			pf->min->left=tl;
			pf->min->left->right=tl;
			tl->left=pf->min->left;
			tl->right=pf->min;
			tl->p=NULL;
		}
		for (;tr!=tr->right;tr=tr->right)
		{
			pf->min->right=tr;
			pf->min->right->left=tr;
			tr->left=pf->min;
			tr->right=pf->min->right;
			tr->p=NULL;
		}
	}	
	z->left->right=z->right;
	z->right->left=z->left;//删除z节点;
	if(z->right==z)//判断原来的z节点是不是仅仅一个
	{
		//是的话
		pf->min=NULL;

	}
	else
		pf->min=z->right;
	consolidate(pf);
	pf->nh=pf->nh-1;

}	

void cut(fbheap* pf,node* x,node* y)
{
	if(y->child==x)//当y的指向孩子的指针是指向x
	{
		if (x->left==x->right==x)//只有x这么一个孩子的时候
		{//可以用一个函数包含下面相同代码,再再次调用可以减少代码量和重复
			y->child=NULL;//孩子是空
			y->degree=0;//仅一个的孩子的时候
		}
		else
		{
			if(x->left!=NULL)//x右非空
			{
				y->child=x->left;
				y->degree=y->degree-1;
			}
			if(x->right!=NULL)//x右非空
			{
				y->child=x->right;
				y->degree=y->degree-1;
			}

		}
	}
	else
	{
		y->degree=y->degree-1;
	}
	x->left=y->left;//插入
	x->right=y;
	y->left->right=x;
	y->left=x;
	x->p=NULL;//父空
	x->mark=false;

}

void cascut(fbheap* pf,node* y)
{
		node* z=y->p;
		if(z!=NULL)
		{
			if(y->mark==false)
				y->mark=true;
			else
			{
				cut(pf,y,z);
				cascut(pf,z);
			}
		}//这里说明一下为什么要进行一个向上回溯,原因是:算法导论P303会证明当一个孩子的2个子节点断了的话,对于菲不拉几堆中的该
		//节点就会和其父节点断了联系,所以就要进行判断是否断了联系
}

void decreatkey(fbheap* pf,node* x,int key)
{
	//输入替换的键值是key,换成小的键值的话就需要
	if(key>x->k)
		cerr<<"出错,输入的键值大了"<<endl;
	else
	{
		x->k=key;
		node* y=x->p;
		//下面判断的是出入的键值是否满足最小堆
		if (y!=NULL&&y->k>x->k)//这个可能么?本身不就是最小堆么?为啥呢?
		{
			cut(pf,x,y);//把x独立出来成为一个根表中的一元。
			cascut(pf,y);//对于x父节点还是要进行一个回溯的
		}
	}
	if (x->k<pf->min->k)
		pf->min=x;
}

void deletekey()
{
	decreatkey(pf,x,-0x7ffffff);

}
下面的都没写了,等过几天再来搞定
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值