二叉堆(Binary_Heap)

      二叉堆满足其结构性,堆序性。结构性:要求为完全二叉树,即除树的最底层外,树被完全填满,且底层的元素从左向右填充。堆序性:即在堆中要求,对任意元素X,X的父节点的关键字小等于X的关键字,如此得到最小堆。同理可得最大堆。  由于堆序性,因此二叉堆也常称为实现优先队列(Priority Queue)。

      在对二叉堆进行操作时需要始终保持其结构性和堆序性。可用数组来实现二叉堆。数组中的元素关系为:i位置上的节点,其左儿子在2i上,右节点在2i+1上,父节点在i/2(取整)上。用数组代替树结构,从而不用包含指针操作。


具体实现代码如下:

Binary_Heap.h:

#ifndef _BINARY_HEAP_
#define __BINARY_HEAP_

class HeapStruct;
typedef HeapStruct* Heap;
typedef int ElementType;

Heap Initialize(int MaxElement);
void Distory(Heap H);
void MakeEmpty(Heap H);
void Insert(ElementType X,Heap H);
ElementType DeleteMin(Heap H);
ElementType FindMin(Heap H);
int IsEmpty(Heap H);
int IsFull(Heap H);

struct HeapStruct {
	int Capacity;
	int Size;
	ElementType *Elements;
};

int MinData=-1;//用于标记


#endif

Binary_Heap.c:

#include "Binary_Heap.h"
#include <stdio.h>

Heap Initialize(int MaxElement)
{
	if (MaxElement<=0)
		return nullptr;

	Heap H=new HeapStruct;
	if(nullptr==H)
		{
		
			printf("out of Space \n");
			return nullptr;
	    }
	H->Elements=new ElementType[MaxElement+1];//第一个元素为MinData标记
	if(nullptr==H->Elements)
	{
		printf("Out of Space \n");
		return nullptr;
	}
	H->Capacity=MaxElement;
	H->Size=0;
	H->Elements[0]=MinData;
 
	return H;
}
void Distory( Heap H)
{
	if(H->Elements!=nullptr)
		delete[] H->Elements;
	delete H;
}
void MakeEmpty(Heap H)
{
	if(H->Elements!=nullptr)
		delete[] H->Elements;
	H->Elements=nullptr;
	H->Size=0;
}
int IsEmpty(Heap H)
{
	if(0==H->Size)
		return 1;
	else 
		return 0;
}
int IsFull(Heap H)
{
	if(H->Size==H->Capacity)
		return 1;
	else 
		return 0;
}
//在尾部插入新元素,并进行上滤操作,直到满足堆序性。
//注意:必满显示的交换赋值操作
void Insert(ElementType X,Heap H)
{
	if(IsFull(H))
		return;
	int i;
	for( i=++H->Size;H->Elements[i/2]>X;i/=2)//用MinData标记来防止i/2越界
		H->Elements[i]=H->Elements[i/2];
	H->Elements[i]=X;//避免显示交换的赋值
}
//删除头部的最小元,并对空穴进行下滤操作,直到满足堆序性。
//注:如何避免显示的交换赋值操作
ElementType DeleteMin(Heap H)
{
 if(IsEmpty(H))
		return H->Elements[0];

 int Child ,i;
 ElementType TempCell;
 ElementType MinElement=H->Elements[1];
 ElementType LastElement=H->Elements[H->Size--];

 for( i=1;i*2<=H->Size;i=Child)//对空穴进行下滤操作,直到满足堆序性
 {
	 Child=i*2;
	 if(Child!=H->Size && H->Elements[Child]>H->Elements[Child+1])//有右儿子,且右儿子更小
		 ++Child;
	 if(LastElement>H->Elements[Child])
		 H->Elements[i]=H->Elements[Child];
	 else 
		 break;
 }
 H->Elements[i]=LastElement;//最后才将该值真正放到空穴中去,避免了显示的交换操作(将两次赋值减少为一次)
 return MinElement;
}
ElementType FindMin(Heap H)
{
	if(IsEmpty(H))
		return H->Elements[0];
	else 
		return H->Elements[1];
}

//简单测试
void main()
{
	Heap H=Initialize(20);
	int A[]={12,2,21,2,45,4,23,4,19,6,21,31,25,22};
	for(int i=0;i<14;++i)
		Insert(A[i],H);
	for(int i=0;i<14;++i)
		A[i]=DeleteMin(H);
	for(int i=0;i<14;++i)//将得到的排序后的元素输出。这也正是堆排序的基本思想
		printf("%d ",A[i]);
}


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值