二叉树之推排序(升序)

简介: 二叉树之推排序(升序)

1.思路

如何将一个堆进行排序,并变成升序?首先,如果要完成升序,那我们可以建立一个大堆,因为大堆可以选出一个最大的值放在堆的最上面,我们就可以根据每次选出一个最大值来进行排序的做法.

1.1大堆的建立方法

值得一说的是,如果给定一个数组,让进行建堆排序操作的话,建立大堆可以有两种不同的过程,两种过程对应了不同的时间复杂度

首先第一种:向上调整法

for (int i = 1; i < n; i++)
{
  AdjustUp(a, i);
}

c74db6367e9c4b1288fe154e7dfc2aae.png

如图所示,时间复杂度为:

O(N*logN)

另一种方法:向下调整法:

与向上调整法不同的是,向下调整法开始的第一个节点是最后一个非叶子节点

for (int i = (n - 1 - 1) / 2; i >= 0; i–)
{
AdjustDown(a, n, i);
}

dd744741b0ab4d68961d2bb59eb8daca.png

如图所示,时间复杂度为:

O(N),

1.2排序的方法

利用大堆的特点,每次选出一个最大值并与最后一个值进行交换,换到最后得到的数组就为排序好的数组.

int end = n - 1;
while (end > 0)
{
  Swap(&a[0], &a[end]);
  AdjustDown(a, end, 0);
  end--;
}

2.代码实现以及测试代码

实现代码:

void Swap(int* p1, int* p2)
{
  int tmp = *p1;
  *p1 = *p2;
  *p2 = tmp;
}
void AdjustUp(int* a, int child)
{
  int parent = (child - 1) / 2;
  while (child > 0)
  {
    if (a[parent] < a[child])
    {
      Swap(&a[parent], &a[child]);
      child = parent;
      parent = (child - 1) / 2;
    }
    else
    {
      break;
    }
  }
}
void AdjustDown(int* a, int size, int parent)
{
  int child = parent * 2 + 1;
  while (child < size)
  {
    if (child + 1 < size && a[child + 1] > a[child])
    {
      ++child;
    }
    if (a[parent] < a[child])
    {
      Swap(&a[parent], &a[child]);
      parent = child;
      child = parent * 2 + 1;
    }
    else
    {
      break;
    }
  }
}
void HeapSort(int* a, int n)
{
  for (int i = (n - 1 - 1) / 2; i >= 0; i--)
  {
    AdjustDown(a, n, i);
  }
  //for (int i = 1; i < n; i++)
  //{
  //  AdjustUp(a, i);
  //}
  int end = n - 1;
  while (end > 0)
  {
    Swap(&a[0], &a[end]);
    AdjustDown(a, end, 0);
    end--;
  }
}

测试代码:

int main()
{ 
  int a[] = { 4,6,2,1,5,8,2,9 };
  int size = sizeof(a) / sizeof(int);
  HeapSort(a, size);
  for (int i = 0; i < size; i++)
  {
    printf("%d ", a[i]);
  }
  return 0;
}

运行截图:

42b6cb9ecba8461f9d8689282b6448a9.png

结尾:今天的分享到此结束,喜欢的朋友如果感觉有帮助可以点赞三连支持,咱们共同进步!

目录
相关文章
如何在C++中实现cpp文件中引用另外一个cpp文件
如何在C++中实现cpp文件中引用另外一个cpp文件
1454 0
|
弹性计算 容灾 关系型数据库
阿里云服务器ECS中扩容云盘后磁盘容量没有增加的解决方法
ECS控制台操作扩容只是扩大云盘的存储容量,不会扩容ECS实例的文件系统。还需要登录实例,然后进行扩容文件系统的操作。
2329 0
阿里云服务器ECS中扩容云盘后磁盘容量没有增加的解决方法
|
9月前
|
网络协议 安全 网络安全
申请通配符 SSL 证书的详细流程
申请通配符SSL证书需明确需求并选择知名CA,选择通配符证书,提交域名信息,通过DNS或邮件验证域名,下载证书文件及私钥。最后在服务器上配置证书和私钥,调整SSL参数,确保网站安全启用加密,提升用户信任。
|
域名解析 网络协议 数据建模
通配符SSL证书申请教程
本文介绍了如何申请和安装通配符SSL证书的步骤:首先选择DV类型的通配符SSL证书并生成CSR,建议使用DNS方式进行验证,随后在域名注册商处添加相应解析记录,待验证通过后,即可下载SSL证书,整个过程大约需要10-15分钟。
|
域名解析 缓存 网络协议
公司网站打开错误怎么回事
公司网站打开错误怎么回事
|
前端开发 Java 程序员
Spring Boot统一功能处理(拦截器, 统一数据返回格式, 统一异常处理)
Spring Boot统一功能处理(拦截器, 统一数据返回格式, 统一异常处理)
727 1
|
机器学习/深度学习 人工智能 算法
机器学习【教育领域及其平台搭建】
机器学习【教育领域及其平台搭建】
399 6
|
中间件 编译器 数据处理
在web开发中应用管道过滤器
【9月更文挑战第1天】本文介绍管道-过滤器架构将数据处理流程分解为一系列独立组件,通过管道连接,适用于数据流处理如图像处理、编译器设计等。通过具体实例说明了Gin如何有效支持管道-过滤器风格的设计,构建高性能Web服务。
289 10
|
JSON 自然语言处理 数据处理
数据标注工具 Label-Studio
数据标注工具 Label-Studio
5226 0
|
人工智能 JavaScript Java
一个简洁、干净的中后台管理模板
nova-admin —— 一个基于Vue3、Vite5、Typescript、Naive UI, 简洁干净后台管理模板。
322 2
一个简洁、干净的中后台管理模板