首先是堆的实现
用堆实现优先级队列
以堆的代码为基础实现:
如果我们给每个元素都分配一个数字来标记其优先级,可以设置较小的数字具有较高的优先级(也可以设置较大的数字),这样我们就可以在一个集合中访问优先级最高的元素并对其进行查找和删除操作了。所以,我们就引入了优先级队列 这种数据结构。 优先级队列(priority queue) 是0个或多个元素的集合,每个元素都有一个优先权。
对优先级队列执行的操作有:
(1)查找
(2)插入一个新元素
(3)删除 一般情况下
查找操作用来搜索优先权最大的元素,删除操作用来删除该元素 。对于优先权相同的元素,可按先进先出次序处理或按任意优先权进行。
#pragma once
#include"Heap.h"
typedef struct Priorityueue
{
Heap _hp;
}PriorityQueue;
// 优先级队列初始化
void PriorityQueueInit(PriorityQueue* q, Compare com);
// 向队列中插入元素
void PriorityQueuePush(PriorityQueue* q, DataType data);
// 删除优先级最高的元素
void PriorityQueuePop(PriorityQueue* q);
// 获取队列中优先级最高的元素
int PriorityQueueSize(PriorityQueue* q);
// 检测优先级队列是否为空
int PriorityQueueEmpty(PriorityQueue* q);
// 获取堆顶的元素
DataType PriorityQueueTop(PriorityQueue* q);
// 销毁优先级队列
void PriorityQueueDestroy(PriorityQueue* q);
优先级队列是以堆为基础,通过堆(大堆或小堆)的排序控制优先级
以数字小优先极高为例,小堆中最小的为根节点,每次删除只需要删除根节点,时间复杂度为O(1),但是插入为O(Logn)
通过插入后自动排序,完成优先级(最小)的判断
#include"Priorityqueue.h"
// 优先级队列初始化
void PriorityQueueInit(PriorityQueue* q, Compare com)
{
InitHeap(&q->_hp,com);//通过com传入大堆还是小堆
}
// 向队列中插入元素
void PriorityQueuePush(PriorityQueue* q, DataType data)
{
InsertHeap(&q->_hp,data);
}
// 删除优先级最高的元素
void PriorityQueuePop(PriorityQueue* q)
{
DeleteHeap(&q->_hp);
}
// 获取队列中优先级最高的元素
int PriorityQueueSize(PriorityQueue* q)
{
return SizeHeap(&q->_hp);
}
// 检测优先级队列是否为空
int PriorityQueueEmpty(PriorityQueue* q)
{
return EmptyHeap(&q->_hp);
}
// 获取堆顶的元素
DataType PriorityQueueTop(PriorityQueue* q)
{
return TopHeap(&q->_hp);
}
// 销毁优先级队列
void PriorityQueueDestroy(PriorityQueue* q)
{
DestroyHeap(&q->_hp);
}
//void test()//用堆封装优先级队列测试
//{
// PriorityQueue q;
// PriorityQueueInit(&q, Less);
//
// PriorityQueuePush(&q, 1);
// printf("%d ->", PriorityQueueTop(&q));
// PriorityQueuePush(&q, 2);
// PriorityQueuePop(&q);
// printf("%d ->", PriorityQueueTop(&q));
// PriorityQueuePush(&q, 3);
// PriorityQueuePop(& q);
// printf("%d ->", PriorityQueueTop(&q));
// PriorityQueuePush(&q, 4);
// PriorityQueuePop(&q);
// printf("%d ->", PriorityQueueTop(&q));
//}
//int main()
//{
// test();
// system("pause");
// return 0;
//}
堆排序
堆这种数据结构而设计的一种排序算法,堆排序是一种选择排序,它的最坏,最好,平均时间复杂度均为O(nlogn),它也是不稳定排序。首先简单了解下堆结构。
堆
堆是具有以下性质的完全二叉树:每个结点的值都大于或等于其左右孩子结点的值,称为大顶堆;或者每个结点的值都小于或等于其左右孩子结点的值,称为小顶堆。如下图:
void HeapAdjust(int* array,int size, int parent)
{
//升序——大堆
int child = parent * 2 + 1;
assert(array);
while (child < size)//左孩子存在
{
if (child + 1 < size && array[child] < array[child + 1])//右孩子存在且大于左孩子
{
child += 1;
}
if (array[child] > array[parent])
{
swap(&array[parent],&array[child]);
parent = child;
child = parent * 2 + 1;
}
else
return;
}
}
void HeapSore(int* array, int size)
{
//建堆
int root = (size - 2) >> 1;//最后一个非叶子节点
int end = size - 1;
for (;root >= 0;--root)
HeapAdjust(array,size, root);
//排序
while (end)
{
swap(&array[0],&array[end]);
HeapAdjust(array,end, 0);
end--;
}
}
void TestHeapSore()
{
int i = 0;
int arr[] = { 53,17,78,9,45,65,87,23,31};
int size = sizeof(arr) / sizeof(arr[0]);
HeapSore(arr, size);
for (; i < size;i++)
{
printf("%d->",arr[i]);
}
printf("\n");
}
int main()
{
TestHeapSore();
system("pause");
return 0;
}
海量数据topK问题
在大规模数据处理中,经常会遇到的一类问题:在海量数据中找出出现频率最好的前k个数,或者从海量数据中找出最大的前k个数,这类问题通常被称为top K问题。例如,在搜索引擎中,统计搜索最热门的10个查询词;在歌曲库中统计下载最高的前10首歌等。
首先将前k个元素构建一个小堆(这样最小的元素就在上面),将剩下的元素遍历比较,若大于堆顶
则替换,这样遍历完后,就得到了前k个最大的数
//n为总数,需要的前k个最大数
void TopK(DataType* a, size_t n, size_t k)
{
size_t i = k;
MakeLessHeap(a,k);//构建小堆
for (i = k; i<n; i++) //遍历剩下的数
{
if (a[i]>a[0])
{
a[0] = a[i];
AdjustDown(a, k, 0);//向下调整
}
}
}