PHP小丑 发表于 2021-12-17 16:06:45

#yyds干货盘点#算法给小码农堆排序至尊骨

堆排序

升序
一种非常正常的想法空间复杂度O(N)
把数组中的元素全都push到小堆中,然后再取堆顶元素重新给数组,就可以达到升序的效果了
堆升序函数HeapSort

//升序
void HeapSort(HPDataType* a,int n)
{
    HP hp;
    HeapInit(&hp);
    int i = 0;
    //建立一个小堆
    for (i = 0; i < n; i++)
    {
      HeapPush(&hp, a);
    }
    //然后把堆顶的元素重新放到数组里面
    for (i = 0; i < n; i++)
    {
      a = HeapTop(&hp);
      //用完pop掉
      HeapPop(&hp);
    }
    HeapDestroy(&hp);
}堆排序测试函数

testHeapSort()
{
    int a[] = { 40,2,0,12,5,454,2323 };
    //堆排序
    HeapSort(a, sizeof(a) / sizeof(a));
    int i = 0;
    for (i = 0; i < sizeof(a) / sizeof(a); i++)
    {
      //把数组里面的元素取出来
      printf("%d ",a);
    }
    printf("\n");
}建堆(向上向下为建堆)
向上调整(建大堆)
==上面做法一点毛病都没有,但是有要求了,空间复杂度为O(1)   也就是我们不可以在用Heap了==
(这里的插入不是真正的插入,因为这些数据原本就在里面,我们就是在调堆,类似插入)


==看到上面打印的结果我们看到建的是小堆,但是不好的是最小的在下标为0的位置,再次找次小的,从下标为一的位置再构建,这是不行的,因为会破坏结构,所以我们要重头建大堆,然后收尾交换==

//真正玩法
void HeapSort(HPDataType* a, int n)
{
    assert(a && n>=0);
    //把数组a构建成堆
    int i = 0;
    for (i = 0; i < n; i++)
    {
      AdjustUp(a,n,i);
    }
}交换排序&&再向上调整

堆排序代码
//真正玩法
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, &a);//根与最后一个数交换
      tail--;
      for (i = 0; i <= tail; i++)
      {
            AdjustUp(a, i);
      }
    }   
}堆排序测试
testHeapSort()
{
    int a[] = { 40,2,50,12,5,454,2323,};
    //堆排序
    HeapSort(a, sizeof(a) / sizeof(a));
    int i = 0;
    for (i = 0; i < sizeof(a) / sizeof(a); i++)
    {
      //把数组里面的元素取出来
      printf("%d ",a);
    }
    printf("\n");
}向下调整
排升序 构建小堆

排升序 构建大堆
有种就是这样玩的

堆排序
//真正玩法
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,&a);//根与最后一个数交换
      AdjustDown(a, i, 0);//向下调整每次都找到次大的数
    }   
}测试堆排序
testHeapSort()
{
    int a[] = { 40,2,50,12,5,454,232,30,3,10 };
    //堆排序
    HeapSort(a, sizeof(a) / sizeof(a));
    int i = 0;
    for (i = 0; i < sizeof(a) / sizeof(a); i++)
    {
      //把数组里面的元素取出来
      printf("%d ",a);
    }
    printf("\n");
}
降序
向上调整(建小堆)

向下调整(建小堆)


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


==所以时间复杂度是O(n)==

            </div>
      
      <div id="asideoffset"></div>

https://blog.51cto.com/u_15443484/4811189
页: [1]
查看完整版本: #yyds干货盘点#算法给小码农堆排序至尊骨