上上篇链接: 堆的实现+堆排序_i跑跑的博客-CSDN博客
目录
分析上上篇堆排序
上篇介绍二叉树笔记在最后实现了一个简单的堆排序:
+
void HeapSort(int* a,int size)
{
HP hp;
HeapInit(&hp);
//时间复杂度O(N*logN)
for (int i = 0;i<size;i++)
{
HeapPush(&hp,a[i]);
}
HeapPrint(&hp);
int j = 0;
//时间复杂度O(N*logN)
while (!HeapEmpty(&hp))
{
a[j] = HeapTop(&hp);
j++;
HeapPop(&hp);
}
HeapDestroy(&hp);
}
优化堆排序
之前是先创建堆,再把数组进行插入,这次我们直接在数组里面进行建堆,令数组变成堆,使堆排序算法的空间复杂度为O(1)
向上调整建堆
为了方便讲解,将堆向上调整在这里展示出来,以建小堆为例
代码实现
//向上调整
//建小堆为例
void Up(HPDataType* a,size_t child)
{
size_t 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;
}
}
}
void HeapSort(int* a,int size)
{
//向上调整建堆
//分析后是件复杂度为O(N*logN)
for (int i = 1;i<size;i++)
{
Up(a,i);
}
}
向下调整建堆
代码实现
//建小堆为例
void Down(HPDataType* a, size_t parent, size_t size)
{
size_t child = parent * 2 + 1;
while (child < size)
{
if (child + 1 <size && 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 HeapSort(int* a,int size)
{
//向下调整建堆
//分析后是件复杂度为O(N+logN)=O(N)
for (int i = (size-1-1)/2; i>=0; i--)
{
Down(a,i, size);
}
}
总结
排序
这样堆排序就可以实现啦
决定升序还是降序,创建大堆或小堆即可
TOP-K问题
什么是TOP-K问题?
思路
代码实现
//TOP-K问题
void PrintTopK(int* a, int n, int k)
{
// 1. 建堆--用a中前k个元素建堆
int* kHeap = (int*)malloc(sizeof(int)*k);
if (kHeap == NULL)
{
printf("malloc fail\n");
exit(-1);
}
//将前k个数插入数组kHeap中
for (int i = 0;i<k;i++)
{
kHeap[i] = a[i];
}
//在数组里面建小堆
for (int i = (k - 1 - 1) / 2; i >= 0; i--)
{
Down(a, i, k);
}
// 2. 将剩余n-k个元素依次与堆顶元素交换,不满则则替换
for (int i = k;i<n;i++)
{
if (a[i]>kHeap[0])
{
kHeap[0] = a[i];
Down(kHeap,0,k);
}
}
// 3. 打印最大或最小的前k个
for (int j = 0;j<k;j++)
{
printf("%d ",kHeap[j]);
}
printf("\n");
free(kHeap);
}
随机数据测试
添加排序程序
//TOP-K问题
void PrintTopK(int* a, int n, int k)
{
// 1. 建堆--用a中前k个元素建堆
int* kHeap = (int*)malloc(sizeof(int)*k);
if (kHeap == NULL)
{
printf("malloc fail\n");
exit(-1);
}
//将前k个数插入数组kHeap中
for (int i = 0;i<k;i++)
{
kHeap[i] = a[i];
}
//在数组里面建小堆
for (int i = (k - 1 - 1) / 2; i >= 0; i--)
{
Down(a, i, k);
}
// 2. 将剩余n-k个元素依次与堆顶元素交换,不满则则替换
for (int i = k;i<n;i++)
{
if (a[i]>kHeap[0])
{
kHeap[0] = a[i];
Down(kHeap,0,k);
}
}
// 3. 排序
//最后一个数据的下标
size_t end = k - 1;
while (end>0)
{
swap(&kHeap[0], &kHeap[end]);
Down(kHeap, 0, end);
end--;
}
// 4. 打印排序后的前k个
for (int j = 0;j<k;j++)
{
printf("%d ",kHeap[j]);
}
printf("\n");
free(kHeap);
}
堆排序和TOP-K问题的笔记到这里就结束啦,欢迎各位伙伴在留言区里交流评价噢,求赞求赞求赞!!!