数据结构:堆

堆的底层是一个顺序表,对这个顺序表进行特定的操作
物理上是一个数组
逻辑上是一个二叉树

在这里插入图片描述

插入

向上调整,只需要调整新插入数据的那一族
因为这个数据在插入前,数组已经是一个堆了
在这里插入图片描述


void push(Hp* pheap, int x)
{
	//插入数据插到数组的最后一层
	assert(pheap);
	if (pheap->capacity == pheap->size)
	{
		int newcapcity = pheap->capacity == 0 ? 4 : pheap->capacity * 2;
		int* tmp = realloc(pheap->a, sizeof(int) * newcapcity);
		pheap->a = tmp;
		pheap->capacity = newcapcity;
	}
	pheap->a[pheap->size] = x;
	++pheap->size;

	//保持数组仍是堆,需要向上调整算法,依次和父亲比较
	up(pheap->a, (pheap->size) - 1);
}

向上调整

void swap(int* a, int* b)
{
	int t = *a;
	*a = *b;
	*b = t;
}
void up(int* a, int child)//向上调整
{
	int parent = (child - 1) / 2;
	while (child > 0)//不满足小堆则调整,只要满足了就break
	{
		if (a[parent] > a[child])
		{
			swap(&a[parent], &a[child]);
			child = parent;
			parent = (child - 1) / 2;
		}
		else
			break;
	}
}

删除

void pop(Hp* pheap)
{
	//删除堆顶的数据
	swap(&(pheap->a[0]), &(pheap->a[pheap->size - 1]));
	(pheap->size)--;
	down(pheap->a, (pheap->size) - 1);
}

向下调整算法

void down(int* arr, int size, int i)
{
	int parent = i;//一般i是0
	int child = parent * 2 + 1;

	while (child < size)
	{
		if (child + 1 < size && arr[child] > arr[child + 1])
		{//找到两个孩子中的较小的
			child++;
		}
		if (arr[parent] > arr[child])
		{
			swap(&arr[child], &arr[parent]);
			parent = child;
			child = parent * 2 + 1;
		}
		else
			break;
	}
}

向下调整时,child默认是左孩子,child+1也要<size

堆排序

在这里插入图片描述

直接在给的数组上原地建堆,for循环建堆
因为是原地建堆,所以排升序建大堆

void HeapSort(int* a, int n)
{
	// 向上调整--建堆 O(N*logN)
	//for (int i = 1; i < n; ++i)
	//{
	//	AdjustUp(a, i);
	//}

	// 向下调整--建堆 O(N),从倒数第一个非叶子节点开始,使用向下调整算法建堆
	for (int i = (n - 1 - 1) / 2; i >= 0; --i)
	{
		Down(a, n, i);
	}

	int end = n - 1;
	while (end > 0)
	{
		Swap(&a[0], &a[end]);
		Down(a, end, 0);
		--end;
	}
}

在这里插入图片描述

top-k

void PrintTopK(int* a, int n, int k)
{
	// 1. 建堆--用a中前k个元素建堆
	int* kminHeap = (int*)malloc(sizeof(int)*k);
	assert(kminHeap);

	for (int i = 0; i < k; ++i)
	{
		kminHeap[i] = a[i];
	}

	// 建小堆
	for (int j = (k - 1 - 1) / 2; j >= 0; --j)
	{
		AdjustDown(kminHeap, k, j);
	}

	// 2. 将剩余n-k个元素依次与堆顶元素交换,不满则则替换
	for (int i = k; i < n; ++i)
	{
		if (a[i] > kminHeap[0])
		{
			kminHeap[0] = a[i];
			AdjustDown(kminHeap, k, 0);
		}
	}

	for (int j = 0; j < k; ++j)
	{
		printf("%d ", kminHeap[j]);
	}
	printf("\n");
	free(kminHeap);
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值