PHP排序算法之堆排序(Heap Sort)实例详解

PHP排序算法之堆排序(Heap Sort)实例详解

什么是堆排序?

堆排序(Heap Sort)是一种树形选择排序,是对直接选择排序的有效改进。

堆排序的过程是将待排序的序列构建成一个大根堆(或小根堆),此时整个序列的最大(或最小)值就是堆顶的根节点。

将其与堆数组的末尾元素进行交换,此时末尾就为最大(或最小)值。

然后将剩余n-1个元素重新构造成堆,这样就会得到n个元素的次小值。

重复执行此步骤直到排序完成。

实现堆排序

1.构建大根堆

使用数组来表示堆,第一个节点是父节点,从它开始一直到最后一个节点,下标值连续增加。

堆的构建是从最后一个非叶子节点开始的,直到根节点,具体实现为:

// 建立大顶堆
function buildMaxHeap(&$arr, $heapSize)
{
    // 取得最后一个非叶子节点
    $lastParentNode = intval(($heapSize - 1) / 2);

    // 从最后一个非叶子节点开始向上构造最大堆
    for ($i = $lastParentNode; $i >= 0; $i--) {
        heapify($arr, $heapSize, $i);
    }
}

2.堆化过程

建立大根堆后,需要进行堆化,使堆满足最大堆的特点。

父节点的值大于它的左右子节点,但是左右子节点之间并无大小之分,所以需要比较左右子节点的大小,找出较大的一个与父节点比较。

// 堆化
function heapify(&$arr, $heapSize, $i)
{
    $left = $i * 2 + 1;
    $right = $i * 2 + 2;
    $largest = $i;

    // 比较父节点、左子节点和右子节点的大小
    if ($left < $heapSize && $arr[$left] > $arr[$largest]) {
        $largest = $left;
    }
    if ($right < $heapSize && $arr[$right] > $arr[$largest]) {
        $largest = $right;
    }

    // 如果最大值不是父节点,就交换位置并堆化
    if ($largest != $i) {
        swap($arr, $i, $largest);
        heapify($arr, $heapSize, $largest);
    }
}

3.堆排序实现

建立好的大根堆是按照顺序存储在数组中的,不需要再次调整节点,直接将根节点与末尾节点交换位置,便可以将末尾节点加入有序区间。

随着节点的减少,剩下的节点可能不再满足最大堆的特点,需要进行再次堆化。

// 堆排序
function heapSort(&$arr)
{
    $heapSize = count($arr);

    // 构建大根堆
    buildMaxHeap($arr, $heapSize);

    // 根节点与末尾交换,并堆化
    for ($i = $heapSize - 1; $i >= 1; $i--) {
        swap($arr, 0, $i);
        $heapSize--;
        heapify($arr, $heapSize, 0);
    }
}

堆排序示例

示例1

$arr = [22, 5, 11, 41, 45, 26, 29, 10, 7, 8, 30];

// 堆排序
heapSort($arr);

// 输出
foreach ($arr as $value) {
    echo "$value ";
}

输出结果为:5 7 8 10 11 22 26 29 30 41 45

示例2

$arr = [31, 24, 17, 20, 16, 19, 5, 10, 12, 4, 8, 14, 9, 7, 2];

// 堆排序
heapSort($arr);

// 输出
foreach ($arr as $value) {
    echo "$value ";
}

输出结果为:2 4 5 7 8 9 10 12 14 16 17 19 20 24 31

通过两个示例可以看出,堆排序是一种十分高效的排序算法,也适用于较大的数据集。堆排序的核心是构建大根堆,并进行堆化,非常适合于排序、查找前k个最大/小值,以及优先队列等应用场景。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:PHP排序算法之堆排序(Heap Sort)实例详解 - Python技术站

(0)
上一篇 2023年5月26日
下一篇 2023年5月26日

相关文章

  • java实现日历窗口小程序

    Java实现日历窗口小程序攻略 1. 实现思路 要实现一个日历窗口小程序,可以考虑以下几个步骤: 创建一个Swing界面,显示当前日期以及日历窗口。 在日历窗口中显示当前月份的日历。 提供按钮或其他交互方式,让用户可以切换月份,也可以选择某一天进行其他操作。 2. 示例1:显示当前月份的日历 下面是一个简单的实现示例,可以通过一个二维数组表示一个月份的日历:…

    Java 2023年5月20日
    00
  • Spring循环引用失败问题源码解析

    下面就为大家详细讲解一下“Spring循环引用失败问题源码解析”的完整攻略。 1. 问题背景 在Spring中,设置成员变量注入时,会遇到“循环引用”的问题。即,在两个类中,它们互相持有对方对象时,Spring容器初始化时会出现错误。 2. 循环引用失败原理 导致循环引用的根本原因,是Java中对象的创建流程涉及到对象的实例化和初始化。在一个Java对象实例…

    Java 2023年5月19日
    00
  • java实现文件打包压缩输出到浏览器下载

    下面是Java实现文件打包压缩输出到浏览器下载的详细攻略。 一、引入相关依赖 我们需要使用Java自带的ZipOutputStream类和ServletOutputStream类来实现文件压缩和下载功能。 import java.io.BufferedInputStream; import java.io.BufferedOutputStream; impo…

    Java 2023年5月26日
    00
  • SpringBoot热重启配置详解

    Spring Boot热重启是指在开发过程中,修改代码后无需手动重启应用程序,而是自动重新加载修改后的代码并更新应用程序。这大大提高了开发效率。下面是Spring Boot热重启的配置详解: 1. 使用Spring Boot DevTools实现热重启 Spring Boot DevTools是Spring Boot提供的一个开发工具,其中包含了热重启功能。…

    Java 2023年5月14日
    00
  • 使用Docker部署Spring Boot的方法示例

    请先阅读以下关于“使用Docker部署Spring Boot的方法示例”的完整攻略: 1. 准备工作 要使用Docker来部署你的Spring Boot应用程序,你需要以下几个组件: Docker Engine Docker Compose Spring Boot应用程序的可执行jar文件 Dockerfile 安装Docker Engine 最新版本的Do…

    Java 2023年5月20日
    00
  • Spring框架事务属性中事务隔离级别与传播行为全面讲解

    Spring框架事务属性中事务隔离级别与传播行为全面讲解 Spring框架提供了丰富的事务管理机制,其中包括事务隔离级别和事务传播行为。本文将详细介绍它们的操作方式以及应用场景。 事务隔离级别 在数据库中,同一时间段内可能有多个会话并发地访问数据库,这时候就需要保证数据的正确性和一致性。传统的数据库并发控制有两种方式:悲观锁和乐观锁。悲观锁会在每次操作前将数…

    Java 2023年5月19日
    00
  • Java全面细致讲解Cookie与Session及kaptcha验证码的使用

    Java全面细致讲解Cookie与Session及kaptcha验证码的使用 在Java Web开发中,Cookie、Session和验证码(kaptcha)是常见的几个概念。本篇文章将全面讲解这几个概念的细节,并通过示例来演示如何使用它们。 Cookie 什么是Cookie? Cookie是一种在客户端(浏览器)中保存数据的机制,通常用于记录用户的状态、用…

    Java 2023年6月15日
    00
  • 线上dubbo线程池耗尽CyclicBarrier线程屏障异常解决记录

    下面我来详细讲解“线上dubbo线程池耗尽CyclicBarrier线程屏障异常解决记录”的完整攻略。 问题背景 最近在自己开发的一个微服务中,使用了Dubbo框架(版本2.6.5),在线上运行时突然出现了一个严重的问题:dubbo线程池耗尽CyclicBarrier线程屏障异常。具体表现为调用Dubbo服务时,服务提供方无法及时响应请求,出现了较长时间的等…

    Java 2023年5月26日
    00
合作推广
合作推广
分享本页
返回顶部