目录
一、堆排序(降序为例)
一、建堆
有一个数组a,数组中有n个元素,首先将要排序的数组调整为小堆,有以下两种思路:
①向上调整建堆
我们以a[0]为堆顶元素,依次插入后面的数并且向上调整,从上往下逐步完善这个小堆
for (int i = 1; i < n; i++) { AdjustUp(a, i); } void AdjustUp(int * a, int child) { int parent = (child-1) / 2; while ( child>0 ) { if (a[child] < a[parent]) { Swap(&a[child], &a[parent]); child = parent; parent = (child - 1) / 2; } else { break; } } }
②向下调整建堆
从最后一个数据的双亲节点开始向下调整,从下往上逐步完善这个小堆
for (int i = (n - 1 - 1) / 2; i >= 0; i--) { AdjustDown(a, n, i); } //向下调整 void AdjustDown(int* a, int n, int parent) { int child = parent * 2 + 1; while (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; } } }
二、排序
我们已经建立了一个小堆,如何将这个小堆进行降序排序呢?
我们可以将堆顶元素与最后一个元素进行交换,这个时候最后一个元素是最小的元素,同时将前n-1个数据看成堆,对堆顶元素进行向下调整,这个时候堆顶元素是次小的元素,再与第n-1个元素进行交换,重复上面步骤,这个时候倒数第二个是次小的元素。一直到最后我们完成了降序排序。
int end = n - 1; while (end > 0) { Swap(&a[0], &a[end]); AdjustDown(a, end, 0); end--; }
二、解决Top-K问题
一、Top-K是什么?
像我们熟悉的战力排行榜,年级前十名等等,就是我们常说的Top-K问题。
Top-K问题:求数据中前K个最大的元素或者最小的元素
二、如何解决Top-K
解决Top-K问题呢,主要有三个步骤,下面我们假设取前K个最大的数
1.建立含K个数据的小堆
2.后面的数依次与堆顶元素作比较,如果比堆顶元素大,则用它替换堆顶元素,替换后向下调整重新变为一个小堆
3.经过上面两个步骤,我们建的小堆已经包含了前K个最大的数,接下来就是对这个堆进行堆排序
三、代码实现
void PrintPopK(int* a, int n, int k) { //建立K个数的堆(前K个最大的,建小堆;前K个最小的,建大堆) for (int i = (k - 2) / 2; i >= 0; i--) { AdjustDown(a, k, i); } //比较 for (int i = k; i < n; i++) { if (a[i] > a[0]) { a[0] = a[i]; AdjustDown(a, k, 0); } } //排序 int end = k - 1; while (end > 0) { Swap(&a[0], &a[end]); AdjustDown(a, end, 0); end--; } for (int i = 0; i < k; i++) { cout << a[i] << ' '; } } //交换 void Swap(HPDataType* p1, HPDataType* p2) { HPDataType tmp = *p1; *p1 = *p2; *p2 = tmp; }
今天的分享就到这里啦,大家觉得有用的话,关注关注点个赞吧!!!
欢迎各位优秀的uu评论区指正~