堆及其操作

本文详细介绍了最大堆的定义,如何使用C语言实现最大堆的创建、插入和删除操作,以及两种构建最大堆的方法。重点讲解了堆的数据结构、最大堆的性质以及维护堆有序性的关键算法PercDown和BuildHeap。
摘要由CSDN通过智能技术生成

堆的定义

采用完全二叉树储存的优先队列称为堆
将该二叉树的宽度优先遍历储存在数组中

完全二叉树:编号为i的结点与完全二叉树编号为i的结点位置相同

在优先队列中,元素被赋予优先级。当访问元素时,具有最高优先级的元素最先删除。优先队列具有最高级先出 (first in, largest out)的行为特征

最大堆

根节点到任一结点的关键字序列保持非递增

最小堆

根节点到任一结点的关键字序列保持非递减

堆的操作

创建

struct HNode{
	int *Data;//储存元素的数组
	int Size;//堆中当前元素的个数
	int Capacity;//堆的最大容量
}
typedef struct HNode* Heap;
typedef Heap MaxHeap;

MaxHeap CreateHeap(int MaxSize){
//容量为Maxsize的空的最大堆
	MaxHeap h=(MaxHeap)malloc(sizeof(struct HNode));
	h->Data=(int*)malloc((Maxsize+1*sizeof(int));
	h->Size=0;
	h->Capacity=Maxsize;
	h->Data[0]=INT_MAX;//换成INT_MIN同样适用于最小堆,Data[0]作为哨兵不记录值
	return h;
}

插入

新增节点先存入数组末尾,然后向上渗透

bool insert(MaxHeap h, int x){
	int i;
	if(IsFull(h){
		printf("最大堆已满");
		return false;
	}
	i=+++h->Size;//i指向堆中数组的最后一个位置
	for(;h->Data[i/2]<x;i/2){//每次和该节点的父节点进行比较
		h->Data[i]=h->Data[i/2];//向上渗透
	}
	h->Data[i]=x;//插入x
	return true;
}

删除

总是最先删除根结点
删除的过程中要保持完全二叉树的结构特性

int DeleteMax(MaxHeap h){
	//从最大堆取出根结点(最大的元素),并删除一个结点
	int parent child;
	int maxItem x;
	if(IsEmpty(h)){
		printf("最大堆已满")return ERROR;
	}
	MaxItem=h->Data[1];//取出根结点中存放的最大值
	//只能取末尾元素作为新的根结点,否则不是完全二叉树
	x=h->Data[h->Size--];//取出末尾元素,并将堆大小减一
	//将x作为新的根从根节点开始下滤,将数组中的元素重新排列
	for(parent=1;parent*2<=h->Size;parent=child){
		child=parent*2;
		if(child!=h->size && h->Data[child] < h->Data[child])
		//上浮的结点必须是较大的子结点,否则从上到下遍历时不满足最大堆(如果较小结点a上浮,则从上向下遍历时,a<较大子结点b)
			child++;//child指向左右子结点较大者或惟一结点
		if(x >= h->Data[child])
			break;//找到合适位置
		else//下滤x
			h->Data[parent]=h->Data[child];
	}
	h->Data[parent]=x;
	return MaxItem;
}

建立

将已存在的n个元素按照最大堆的要求存放在一个一维数组中

方法一:通过最大堆的插入操作将n个元素相继插入空的堆中去

方法二:
1,将n个元素按顺序存入二叉树中,只满足完全二叉树的结构特性即可
2,调整各结点元素,以满足最大堆的有序性

void PercDown(MaxHeap h, int p){
	//下滤,将以h->Data[p]为根的子堆调整为最大堆
	int parent,child;
	int x;
	x=h->Data[p];
	for(parent=p;parent*2 <= h->Size;parent=child){
		child=parent*2;
		if(child != h->Size && h->Data[child] < h->Data[child+1])
			child++;//child指向左右结点较大值
		if(x >= h->Data[child])
			break;//找到了合适的位置
		else
			h->Data[parent]=h->Data[child];//下滤x
	}
	h->Data[parent]=x;
}

void BUildHeap(MaxHeap h){
	//调整h->Data[]中的元素,满足最大堆的有序性
	int i;
	//从最后一个结点的父节点开始,到根结点1
	for(i=h->Size/2;i>0;i--){
		PercDown(h,i);
	}
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值