代码还没写完,但是么得啥时间去修改,先把昨晚写的粘上来,过几天把万恶的啥完成了在来修改,备注一下。
#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);
}
下面的都没写了,等过几天再来搞定