当前位置: 首页 > article >正文

[数据结构]排序之 堆排序详解

目录

一、建堆

二、利用堆删除思想来进行排序 

三、堆排序的时间复杂度 


一、建堆

  • 升序:建大堆
  • 降序:建小堆
建堆方式:
向上调整建堆:模拟的是插入数据的过程
//排升序建大堆
void HeapSort(int* a, int n)
{
       //建大堆
       for (int i = 1; i < n; i++)
       {
              AdjustUp(a, i);
       }
}

向下调整建堆(左右子树必须是大堆或小堆(插入之前得是堆)):

void HeapSort(int* a, int n)
{
       //向下调整建堆
       for (int i = (n - 1 - 1) / 2; i >= 0;--i)//先找到最后一个非叶子结点即上图的6 n-1是最后一个数据的下标,再-1除以2就是父节点
       {
              AdjustDown(a, n, i);
       }
}

注:向下建堆的效率O(N)比向上建堆的效率O(N*logN)高

数学证明如下:        

二、利用堆删除思想来进行排序 

建堆和堆删除中都用到了向下调整,因此掌握了向下调整,就可以完成堆排序。

三、堆排序的时间复杂度 

所以如果用来排序的话,无论是向上调整还是向下调整建堆,总的时间复杂度都是O(N*logN) 

#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<assert.h>
#include<stdlib.h>
#include<assert.h>

typedef int HPDataType;
//向下调整
void AdjustDown(HPDataType* a, int n, int parent)
{
       int child = parent * 2 + 1;//先默认左孩子大
       while (child < n)
       {
              //选出左右孩子中大的那一个  右孩子和左孩子的关系:大一
              if (child + 1 < n && a[child + 1] > a[child])
              {
                      ++child;
              }
              if (a[child] > a[parent])
              {
                      Swap(&a[child], &a[parent]);
                      parent = child;
                      child = parent * 2 + 1;
              }
              else
              {
                      break;
              }
       }
}
//O(n*logn)
//排升序建大堆
void HeapSort(int* a, int n)
{
       //向下调整建堆
       for (int i = (n - 1 - 1) / 2; i >= 0; --i)//n-1是最后一个数据的下标,再-1除以2就是父节点
       {
              AdjustDown(a, n, i);
       }
       int end = n - 1;
       while (end > 0)
       {
              Swap(&a[end], &a[0]);
              AdjustDown(a, end, 0);
              --end;
       }
}
int main()
{
       printf("调整前:");
       int a[10] = { 2,1,5,7,6,8,0,9,3 };
       for (int i=0;i<9;i++)
       {
              printf("%d ", a[i]);
       }
       printf("\n");
       HeapSort(a, 9);
       printf("调整后:");
       for (int i = 0; i < 9; i++)
       {
              printf("%d ", a[i]);
       }
       return 0;
}

 


http://www.kler.cn/a/593113.html

相关文章:

  • 先有OLE还是先有COM?
  • xss漏洞基础整理
  • podspec语法
  • MyBatis 传递多个参数的方式
  • 原生JavaScript控制页面跳转的几种方式
  • git tag常用操作
  • Springboot项目打包成war包
  • AJAX PHP:深入理解与实际应用
  • 基于SpringBoot + Vue 的药店药品信息管理系统
  • 基于Spring Boot的本科生交流培养管理平台的设计与实现(LW+源码+讲解)
  • QT--按键事件与定时器事件
  • 【一起来学kubernetes】15、Job使用详解
  • Node.js 中使用 RabbitMQ
  • linux-----------------指令下集
  • 微服务的网关配置
  • springboot集成xxl-job
  • YOLOv8模型修改与CA注意力机制详解
  • Qwen2-Audio:通义千问音频大模型技术解读
  • FPGA实现LED流水灯(开发板为DE2-115)
  • C#:深入理解Thread.Sleep与Task.Delay