堆的概念

如果有一个关键码的集合K={k0,k1,k2,…,kn-1},把它的所有元素按完全二叉树的顺序存储方式存储在一个一维数组中,并满足:K[i] <= K[2i+1] 且 Ki<= K[2i+2] (K[i] >= K[2i+1] 且 K[i] >= K[2i+2]) i =
0,1,2…,则称为小堆(或大堆)。

大小堆

  • 堆的特点

小(大)堆中任一结点的关键码均小于(大于)等于它的左右孩子的关键码,位于堆顶结点的关键码最小(最大),从根节点到每个结点的路径上数组元素组成的序列都是递增(递减)的

堆的创建

思路

从最后一个非叶子结点开始调整,一直到根节点为止,将每个结点及其子
树调整到满足堆的性质即可

建堆

typedef struct Heap
{
	int array[100];
	int size;
} Heap;

// 初始化堆
void HeapInit(Heap* pH, int source[], int size)
{
	for (int i = 0; i < size; i++)
	{
		pH->array[i] = source[i];
	}
	pH->size = size;
}

// 向下调整
void HeapAdjustDown(Heap* pH, int root)
{
	int parent = root;
	while (1)
	{
		int left = 2 * parent + 1;
		if (left >= pH->size)
		{
			return;
		}
		int maxChild = left;
		if (2 * parent + 2 < pH->size && pH->array[2 * parent + 2] > pH->array[left])
		{
			maxChild = 2 * parent + 2;
		}
		if (pH->array[parent] > pH->array[maxChild])
		{
			return;
		}

		// 交换 root 和 maxChild 下标所在的值
		int t = pH->array[parent];
		pH->array[parent] = pH->array[maxChild];
		pH->array[maxChild] = t;

		parent = maxChild;
	}
}
// 建大堆
void MakeHeap(Heap* pH)
{
	for (int i = (pH->size - 2) / 2; i >= 0; i--)
	{
		HeapAdjustDown(pH, i);
	}
}

result

堆的插入和删除
  • 删除(每次删除堆顶元素)

思路

  1. 将堆中最后一个元素代替堆顶元素
  2. 将堆中元素个数减少一个(相当于删除最后一个元素)
  3. 向下调整使其满足对的性质
void HeapPop(Heap *pH)
{
	pH->array[0] = pH->array[pH->size - 1];
	pH->size--;

	HeapAdjustDown(pH, 0);
}

popresult

  • 插入

思路

在已经建成的堆的后面插入新元素,插入之后,当树中结点不满足堆的性质时,就需要对堆进行重新调整(向上调整)

// 向上调整
void HeapAdjustUp(Heap *pH, int child)
{
	int parent;
	while (child > 0) {
		parent = (child - 1) / 2;
		if (pH->array[parent] >= pH->array[child]) {
			return;
		}

		Swap(pH->array + parent, pH->array + child);

		child = parent;
	}
}
// 插入元素
void HeapPush(Heap *pH, int data)
{
	assert(pH->size < 100);
	pH->array[pH->size++] = data;
	HeapAdjustUp(pH, pH->size - 1);
}

pushresult
本文原码已上传至github:https://github.com/Sveter/C/tree/master/Heap

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值