算法给小码农堆排序至尊骨

简介: 算法给小码农堆排序至尊骨

文章目录


堆排序

升序

一种非常正常的想法 空间复杂度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[i]);
  }
  //然后把堆顶的元素重新放到数组里面
  for (i = 0; i < n; i++)
  {
    a[i] = HeapTop(&hp);
    //用完pop掉
    HeapPop(&hp);
  }
  HeapDestroy(&hp);
}

堆排序测试函数

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了

(这里的插入不是真正的插入,因为这些数据原本就在里面,我们就是在调堆,类似插入)

看到上面打印的结果我们看到建的是小堆,但是不好的是最小的在下标为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[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");
}

向下调整

排升序 构建小堆

排升序 构建大堆

有种就是这样玩的

堆排序
//真正玩法
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");
}


降序

向上调整 (建小堆)

向下调整(建小堆)

建堆的时间复杂度

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

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


目录
相关文章
|
5月前
|
算法 Python
数据结构算法--4堆排序
堆排序过程概述:建立大根堆,将堆顶最大元素移出并替换为末尾元素,调整保持堆性质,重复此过程直至堆为空,实现排序。时间复杂度为O(nlogn)。Python中可用heapq模块进行堆操作。
|
6月前
|
机器学习/深度学习 人工智能 算法
数据结构与算法:堆排序和TOP-K问题
朋友们大家好,本节内容来到堆的应用:堆排序和topk问题
数据结构与算法:堆排序和TOP-K问题
|
6月前
|
存储 人工智能 算法
深入浅出堆排序: 高效算法背后的原理与性能
深入浅出堆排序: 高效算法背后的原理与性能
114 1
|
1月前
|
算法 搜索推荐
数据结构与算法学习十八:堆排序
这篇文章介绍了堆排序是一种通过构建堆数据结构来实现的高效排序算法,具有平均和最坏时间复杂度为O(nlogn)的特点。
70 0
数据结构与算法学习十八:堆排序
|
1月前
|
算法 搜索推荐
算法之堆排序
本文介绍了堆排序算法的原理和实现,通过构建最大堆或最小堆,利用堆的性质进行高效的排序,并提供了具体的编程实现细节和示例。
20 0
算法之堆排序
|
1月前
|
算法 Java Go
深入了解堆排序算法
深入了解堆排序算法
22 1
|
6月前
|
移动开发 算法 前端开发
前端算法之堆排序
前端算法之堆排序
40 1
|
5月前
|
搜索推荐 算法 Java
Java中的快速排序、归并排序和堆排序是常见的排序算法。
【6月更文挑战第21天】Java中的快速排序、归并排序和堆排序是常见的排序算法。快速排序采用分治,以基准元素划分数组并递归排序;归并排序同样分治,先分割再合并有序子数组;堆排序通过构建堆来排序,保持堆性质并交换堆顶元素。每种算法各有优劣:快排平均高效,最坏O(n²);归并稳定O(n log n)但需额外空间;堆排序O(n log n)且原地排序,但不稳定。
46 3
|
5月前
|
搜索推荐 算法
【C/排序算法】:堆排序和选择排序
【C/排序算法】:堆排序和选择排序
34 0
|
5月前
|
存储 算法 C语言
数据结构和算法——堆排序(选择排序、思路图解、代码、时间复杂度、堆排序及代码)
数据结构和算法——堆排序(选择排序、思路图解、代码、时间复杂度、堆排序及代码)
36 0