堆《数据结构》

堆《数据结构》

1. 堆排序

1.1 建堆

建大堆
建小堆

向上调整建堆

AdjustUp建堆

c 复制代码
void AdjustUp(HPDataType* a, int child)
{
	// 初始条件
	// 中间过程
	// 结束条件
	int parent = (child - 1) / 2;
	//while (parent >= 0)
	while (child > 0)
	{
		if (a[child] < a[parent])
		{
			Swap(&a[child], &a[parent]);
			child = parent;
			parent = (child - 1) / 2;
		}
		else
		{
			break;
		}
	}
}

void headsport(int* a, int n)//建堆
{
	for (int i = 0;i < n;i++)
	{
		AdjustUp(a, i);//建堆(降序建大堆)向上调整建堆
	}
}
void test1()
{
	int arr[] = {1,5,3,2,7,9,4,6,8};
	headsport(arr, sizeof(arr) / sizeof(arr[0]));
	for (int i = 0;i < sizeof(arr) / sizeof(arr[0]);i++)
	{
			printf("%d", arr[i]);
	}

}

1:我们通过AdjustUp函数来建堆
2:在控制AdjustUp函数中a[child] < a[parent]的大小比较关系,这是控制建小堆,还是建大堆

如:a[child] < a[parent] 建小堆

a[child] > a[parent]建 大堆

向下调整建堆

AdjustDown


c 复制代码
void AdjustDown(HPDataType* a, int n, int parent)
{
	// 先假设左孩子小
	int child = parent * 2 + 1;

	while (child < n)  // child >= n说明孩子不存在,调整到叶子了
	{
		// 找出小的那个孩子
		if (child + 1 < n && a[child + 1] < a[child])
		{
			++child;
		}

		if (a[child] < a[parent])
		{
			Swap(&a[child], &a[parent]);
			parent = child;
			child = parent * 2 + 1;
		}
		else
		{
			break;
		}
	}
}
void headsport(int* arr, int n)
{
	//时间复杂度O(N)
	for (int i = (n-1-1)/2;i >=0;i--)
	{
		AdjustDown(arr,n,i);//向下调整建堆
	}


}
void test1()
{
	int arr[] = {1,5,3,2,7,9,4,6,8};
	headsport(arr, sizeof(arr) / sizeof(arr[0]));
	for (int i = 0;i < sizeof(arr) / sizeof(arr[0]);i++)
	{
			printf("%d", arr[i]);
	}

}

与AdjustUp同理:

arr[child]>arr[parent]->大堆

arr[child]<arr[parent]->小堆

1.2 利用堆删除思想来进行排序

1:建堆

升序:建大堆

降序:建小堆

2:建堆和堆删除中都用到了向下调整,因此掌握了向下调整,就可以完成堆排序。

实现图:

c 复制代码
void headsport(int* arr, int n)
{
	for (int i = (n-1-1)/2;i >=0;i--)
	{
		AdjustDown(arr,n,i);//向下调整建堆
	}
	int end = n - 1;//取最后一位数据
    while (end > 0)
{
	Swap(&arr[0], &arr[end]);//交换
	AdjustDown(arr, end, 0);//在向下建堆
	end--;
}
}
void test1()
{
	int arr[] = {1,5,3,2,7,9,4,6,8};
	headsport(arr, sizeof(arr) / sizeof(arr[0]));
	for (int i = 0;i < sizeof(arr) / sizeof(arr[0]);i++)
	{
			printf("%d", arr[i]);
	}

}
int main()
{
	test1();
	//CreateNdDate();
	/*TestHeap();*/
	/*TestHeap3();*/
	return 0;
}

1.3Top-k问题

TOP-K问题:即求数据结合中前K个最大的元素或者最小的元素,一般情况下数据量都比较大。

比如:专业前10名、世界500强、富豪榜、游戏中前100的活跃玩家等

对于Top-K问题,能想到的最简单直接的方式就是排序 ,但是:如果数据

量非常大,排序就不太可取了(可能数据都不能一下子全部加载到内存中)。最佳的方式就是用堆来解决,基本思路如下:

1.用数据集合中前K个元素来建堆

·前k个最 的元素,则建小堆

·前k个最 的元素,则建大堆

2.用剩余的N-K个元素依次与堆顶元素来比较,不满足则替换堆顶元素

将剩余N-K个元素依次与堆顶元素比完之后,堆中剩余的K个元素就是所求的前K个最小或者最大的元素

c 复制代码
#include<time.h>
#include<stdio.h>
#include<stdlib.h>
#include<stdbool.h>
void CreateNdDate()
{
	//造数据
	int n = 100000;
	srand(time(0));//随机种子
	const char* file = "daf.txt";
	FILE* fin = fopen(file, "w");//打开文件
	if (fin == NULL)
	{
		perror("fopen error");
		return;
	}
	for (int i = 0;i < n;i++)
	{
		int x = (rand() + i) % 1000000;//随机值
		fprintf(fin, "%d\n", x);//写入数据
	}
	fclose(fin);
}

void TestHeap()
{
	int k;//获取前k个数
	printf("请输入k>");
	scanf("%d", &k);
	int* kminheap = (int*)malloc(sizeof(int) * k);
	if (kminheap == NULL)
	{
		perror("mallco fail");
		return;
	}
	const char* file = "data.txt";
	FILE* fout = fopen(file, "r");
	if (fout == NULL)
	{
		perror("fopen error ");
		return;
	}
	//读取文件前k个数
	for (int i = 0;i < k;i++)
	{
		fscanf(fout,"%d", &kminheap[i]);
	}
	for (int i = (k - 1 - 1) / 2;i >= 0;i--)//建小堆
	{
     AdjustDown(kminheap, k, i);
	}
	//读取剩下n-k个数
	int x = 0;
	while (fscanf(fout,"%d", &x)>0);
	{
		if (x > kminheap[0])
		{
			kminheap[0] = x;
			AdjustDown(kminheap, k, 0);
		}
	}
	printf("最大前k个\n");
	for (int i = 0;i < k;i++)
	{
		printf("%d\n", kminheap[i]);
	}

}
int main()
{
	
	CreateNdDate();
	TestHeap();
	
	return 0;
}

2.堆的时间复杂度

因为堆是完全二叉树,而满二叉树也是完全二叉树,此处为了简化使用满二叉树来证明(时间复杂度本来看的就是近似值,多几个结点不影响最终结果):

向下调堆:从最后一个根节点开始调整

向上调堆:

调整次数:

第二层:向上调整 1次

第三层: 向上调整2次

...

...

第n层:向上调整n次
节点个数

第一层:2^0个

第二层:2^1个

...

...

第n层:2^n-1个

感谢大家观看!!!

相关推荐
Chase-Hart14 分钟前
【每日一题】LeetCode 7.整数反转(数学)
java·数据结构·算法·leetcode·eclipse
四角小裤儿儿21 分钟前
Java数据结构(十一)——归并排序、计数排序
java·数据结构·排序算法
朱皮皮呀1 小时前
排序算法-归并排序
数据结构·算法·排序算法·归并排序
jyan_敬言1 小时前
虚拟机centos_7 配置教程(镜像源、配置centos、静态ip地址、Finalshell远程操控使用)
linux·运维·服务器·c语言·数据结构·tcp/ip·centos
UrSpecial1 小时前
【数据结构取经之路】图解AVL树
数据结构
QXH2000001 小时前
数据结构—顺序表
数据结构
fhvyxyci4 小时前
【数据结构初阶】顺序结构二叉树(堆)接口实现超详解
c语言·数据结构
禁默7 小时前
list从0到1的突破
数据结构·c++·list
laocooon5238578867 小时前
一个线性筛的多功能组合:筛法求质数+约数个数+约数和
数据结构·c++·算法
银氨溶液10 小时前
MySQL底层为什么选择用B+树作为索引
数据结构·数据库·b树·mysql·面试·b+树