美人鱼7号

导航

 

最小最大混合堆:

堆序性质为:偶数深度上的任意节点X,存储在X上的关键字小于它的父亲但是大于它的祖父;奇数深度上的任意节点X,存储在X上的关键字大于它的父亲但是小于它的祖父。如下图所示为根据下面的插入方法根据输入1 2 3 4 5 6 7 8 9 10生成的一个最小最大堆:

1、最小最大堆的插入方法

PriorityQueue MinMaxHeapInsert(PriorityQueue Q,int X)
{
	if(IsFull(Q))
		printf("Q is Full,can not insert!");
	else
	{
		Q->size+=1;
		int i=Q->size;
		while(i)
		{
			float flag=log10(i*1.0)/log10(2.0);//C库中没有以2为底的求对数,只能变换一下
			int jiou=(int(flag))%2;//得到i所在深度的奇偶,使用log2(i)%2得到
			if(jiou==0)//偶数深度节点
			{
				if(i/2!=0&&Q->Arr[i/2]<X)//大于父节点互换,互换后i所在的深度奇偶变换,跳到下面的循环
				{
					Q->Arr[i]=Q->Arr[i/2];	
					Q->Arr[i/2]=X;
					i=i/2;
				}
				else if(Q->Arr[i/4]>X)//小于祖父节点互换,互换后i所在的深度奇偶变换,跳到下面的循环
				{
					Q->Arr[i]=Q->Arr[i/4];	
					Q->Arr[i/4]=X;
					i=i/4;
				}
				else//顺序正常不变,直接插入,循环结束
				{
					Q->Arr[i]=X;
					break;
				}
					
			}
			else//奇数深度节点
			{
				if(Q->Arr[i/2]>X)//小于父节点互换,互换后i所在的深度奇偶变换,跳到前面的循环
				{
					Q->Arr[i]=Q->Arr[i/2];
					Q->Arr[i/2]=X;
					i=i/2;
				}
				else if(i/4!=0&&Q->Arr[i/4]<X)//大于祖父节点互换,互换后i所在的深度奇偶变换,跳到前面的循环
				{
					Q->Arr[i]=Q->Arr[i/4];	
					Q->Arr[i/4]=X;
					i=i/4;
				}
				else//顺序正常不变,直接插入,循环结束
				{
					Q->Arr[i]=X;
					break;
				}
					
			}
		}		
	}
	return Q;
}

  

 

2、最小最大堆的DeleteMin操作

int DeleteMinMMHeap(PriorityQueue Q)
{
	if(IsEmpty(Q))
	{
		printf("Empty PriorityQueue!");
		return Q->Arr[0];
	}
	int mindata=Q->Arr[1];
	int lastone=Q->Arr[Q->size--];
	int i=1,minchild;
	int min;
	for(i=1;4*i<=Q->size;i=min)
	{
		min=4*i;
		for(int j=min+1;j<=Q->size&&j<=4*i+3;j++)
		{				
			if(Q->Arr[min]>Q->Arr[j])
				min=j;
		}
		if(Q->Arr[min]<lastone)
			Q->Arr[i]=Q->Arr[min];
		else
			break;
	}
	//递渐找到小值后,最后空出给lastone填充,
	//填完后要看是否符合大小堆规则,不符合继续调整
	//Q->Arr[i]=lastone;
	if(2*i>Q->size)//i在最后一层没有子节点
	{
		if(Q->Arr[i/2]<lastone)
		{
			Q->Arr[i]=Q->Arr[i/2];
			Q->Arr[i/2]=lastone;
		}
		else
			Q->Arr[i]=lastone;
	}
	else if(2*i<=Q->size)//i在次一层可能有1个或2个子节点
	{	
		minchild=2*i;
		if((minchild!=Q->size)&&Q->Arr[minchild]>Q->Arr[minchild+1])
			minchild++;
		if(Q->Arr[minchild]<lastone)
			Q->Arr[i]=Q->Arr[minchild];			
		Q->Arr[minchild]=lastone;
	}
	else if(4*i>Q->size)//i在次二层必有两个子节点
	{
		if(Q->Arr[i/2]<lastone)
		{
			Q->Arr[i]=Q->Arr[i/2];
			Q->Arr[i/2]=lastone;
		}
		minchild=2*i;
		if((minchild!=Q->size)&&Q->Arr[minchild]>Q->Arr[minchild+1])
			minchild++;
		if(Q->Arr[minchild]<Q->Arr[i])
		{
			int temp=Q->Arr[i];
			Q->Arr[i]=Q->Arr[minchild];	
			Q->Arr[minchild]=temp;
		}
		else
			Q->Arr[i]=lastone;
	}
	return mindata;
}

  代码实现的有点粗糙和复杂,特别是删除的方法,也没有充分测试,不知道是否有更简便的方法

posted on 2018-03-01 13:56  美人鱼7号  阅读(1364)  评论(0)    收藏  举报