Hi,大家好,我是编程小6,很荣幸遇见你,我把这些年在开发过程中遇到的问题或想法写出来,今天说一说教你怎样堆排序,希望能够帮助你!!!。
把数组中的元素全都push到小堆中,然后再取堆顶元素重新给数组,就可以达到升序的效果了
image-20211109215923477
//升序
void HeapSort(HPDataType* a,int n)
{
HP hp;
HeapInit(&hp);
int i = 0;
//建立一个小堆
for (i = 0; i < n; i++)
{
HeapPush(&hp, a[i]);
}
//然后把堆顶的元素重新放到数组里面
for (i = 0; i < n; i++)
{
a[i] = HeapTop(&hp);
//用完pop掉
HeapPop(&hp);
}
HeapDestroy(&hp);
}
复制代码
image-20211109220129388
void testHeapSort()
{
int a[] = { 40,2,0,12,5,454,2323 };
//堆排序
HeapSort(a, sizeof(a) / sizeof(a[0]));
int i = 0;
for (i = 0; i < sizeof(a) / sizeof(a[0]); i++)
{
//把数组里面的元素取出来
printf("%d ",a[i]);
}
printf("\n");
}
复制代码
上面做法一点毛病都没有,但是有要求了,空间复杂度为O(1) 也就是我们不可以在用Heap了
(这里的插入不是真正的插入,因为这些数据原本就在里面,我们就是在调堆,类似插入)
image-20211110004419158
image-20211110004843299
看到上面打印的结果我们看到建的是小堆,但是不好的是最小的在下标为0的位置,再次找次小的,从下标为一的位置再构建,这是不行的,因为会破坏结构,所以我们要重头建大堆,然后收尾交换
image-20211112004113756
//真正玩法
void HeapSort(HPDataType* a, int n)
{
assert(a && n>=0);
//把数组a构建成堆
int i = 0;
for (i = 0; i < n; i++)
{
AdjustUp(a,n,i);
}
}
复制代码
image-20211112011348827
//真正玩法
void HeapSort(HPDataType* a, int n)
{
assert(a && n>=0);
//把数组a构建成堆
int i = 0;
//向上调整
for (i = 0; i < n; i++)
{
AdjustUp(a,i);
}
//根与最后一个数交换并每次都找到次大的数
int tail = n - 1;
while (tail)
{
Swap(&a[0], &a[tail]);//根与最后一个数交换
tail--;
for (i = 0; i <= tail; i++)
{
AdjustUp(a, i);
}
}
}
复制代码
void testHeapSort()
{
int a[] = { 40,2,50,12,5,454,2323,};
//堆排序
HeapSort(a, sizeof(a) / sizeof(a[0]));
int i = 0;
for (i = 0; i < sizeof(a) / sizeof(a[0]); i++)
{
//把数组里面的元素取出来
printf("%d ",a[i]);
}
printf("\n");
}
复制代码
image-20211110204752959
有种就是这样玩的
image-20211110234106150
//真正玩法
void HeapSort(HPDataType* a, int n)
{
assert(a && n>=0);
//把数组a构建成堆
int i = 0;
////向上调整
//for (i = 0; i < n; i++)
//{
// AdjustUp(a,n,i);
//}
//向下调整
for (i = (n - 1 - 1) / 2; i >= 0; i--)
{
AdjustDown(a, n, i);
}
//根与最后一个数交换并每次都找到次大的数
int tail = n - 1;
for (i = tail; i > 0; i--)
{
Swap(&a[0],&a[i]);//根与最后一个数交换
AdjustDown(a, i, 0);//向下调整每次都找到次大的数
}
}
复制代码
void testHeapSort()
{
int a[] = { 40,2,50,12,5,454,232,30,3,10 };
//堆排序
HeapSort(a, sizeof(a) / sizeof(a[0]));
int i = 0;
for (i = 0; i < sizeof(a) / sizeof(a[0]); i++)
{
//把数组里面的元素取出来
printf("%d ",a[i]);
}
printf("\n");
}
复制代码
image-20211112012044528
image-20211112012356035
3.2.3 建堆时间复杂度因为堆是完全二叉树,而满二叉树也是完全二叉树,此处为了简化使用满二叉树来证明(时间复杂度本来看的就是近似值,多几个节点不影响最终结果):
image-20211111230047286
image-20211111230800529
所以时间复杂度是O(n)
原链:https://juejin.cn/post/7032900670332076045
今天的分享到此就结束了,感谢您的阅读,如果确实帮到您,您可以动动手指转发给其他人。
上一篇
已是最后文章
下一篇
已是最新文章