堆排序分析及php实现
堆排序:是一种特殊形式的选择排序,他是简单选择排序的一种改进。
什么是堆?
具有n个元素的序列:{k1,k2,ki,…,kn}
(ki <= k2i,ki <= k2i+1) 或者 (ki >= k2i,ki >= k2i+1), (i = 1,2,3,4...n/2)
满足这个条件时,该序列就是一个堆。第一个条件称为小顶堆,第二个条件称为大顶堆。
为了方便,下边论述基于大顶堆,并且下标从1开始。
将堆的元素放在一棵完全二叉树中,方便我们讨论堆的特性和排序,一般谈到堆也都是一棵完全二叉树。
完全二叉树:若二叉树的深度为h,除第 h 层外,其它各层 (1~h-1) 的结点数都达到最大个数,第 h 层所有的结点都连续集中在最左边,这就是完全二叉树。
堆的特性(括号道标下标从0开始的计算方法) :
- 非叶子结点个数:n / 2 (n / 2 - 1)
- 节点i的左子树下标 :2*i (2*i+ 1)
- 节点i的右子树下标:2*i + 1 (2*i + 2)
堆排序:
核心思想:
- 将原始序列构成一个堆。(建立初始堆)
- 交换堆的第一个元素(最大值)和最后一个元素的位置,把堆长度减一后剩余的序列再转换为一个堆。(调整堆)
- 重复2过程n-1次。
经过上述操作,就可以将一个无序序列从小到大排序。(因为大顶堆每次把最大值交换到最后了,所以想要降序排列就要用小顶堆)
先说调堆,调堆就是把当前节点和其左子树,右子树中最大值交换,依次把需要调整的节点调一遍。这样一次循环下来根节点肯定放的是最大值。但是有可能循环中的某次交换把之前排好序的结构打乱,需要递归调整。
再说建堆,建堆就是从最后一个非叶子节点开始,到第一个节点为止,依次进行调堆。
for ($i = floor(count($arr) / 2) - 1; $i >=0; $i--) {
adjustHeap($arr);
}
借用网上的一张图说明一下:

从floor(9/2)-1开始,也就是key=3,val=5的地方开始,循环调堆,到图1.6处循环完成,最大值顺利到达根节点,但是发现val=1节点还是需要调整,这就需要在调堆里执行循环调整,使其符合堆的特性。
代码实现:
$arr = [49, 38, 65, 97, 76, 13, 27, 50];
sortHeap($arr);
print_r($arr); function sortHeap(&$arr)
{
//先建堆
buildHeap($arr); //把第一个节点和最后一个节点交换,直到节点数为1
$count = count($arr);
while ($count > 1) {
swap($arr, $count - 1, 0); //交换第一个和最后一个元素
$count--; //去掉最后一个元素后剩余元素再进行调整
adjustHeap($arr, $count, 0);
}
} function buildHeap(&$arr)
{
$node = floor(count($arr) / 2) - 1; //非叶子节点的最大节点,下标从0开始
for ($i = $node; $i >= 0; $i--) { //从最大非叶子节点循环调整每个节点
adjustHeap($arr, count($arr), $i);
}
} //调整堆,接受maxLen为当前堆需要调整的元素最大值,node为当前要调整的节点
function adjustHeap(&$arr, $maxLen, $node)
{
$lchild = 2 * $node + 1; //左子树
$rchild = 2 * $node + 2; //右子树 $max = $node; //设置当前节点为最大值的节点,方便后边最大值节点变化时与当前节点比较,确认是否需要交换 while ($lchild < $maxLen || $rchild < $maxLen) { //左子树和右子树任一个符合条件就进入循环 if ($lchild < $maxLen && $arr[$lchild] > $arr[$max]) { //左子树大于当前节点值得话设置设置$max
$max = $lchild;
} if ($rchild < $maxLen && $arr[$rchild] > $arr[$max]) {
$max = $rchild;
} if ($max != $node) {
swap($arr, $max, $node);
$node = $max; //把当前节点切换为最大值的那个节点,迭代使其符合堆特性
$lchild = 2 * $node + 1;
$rchild = 2 * $node + 2;
} else {
break; //没有发生交换就退出
}
}
} function swap(&$arr, $m, $n)
{
$arr[$m] = $arr[$m] ^ $arr[$n];
$arr[$n] = $arr[$n] ^ $arr[$m];
$arr[$m] = $arr[$m] ^ $arr[$n];
}
堆排序分析及php实现的更多相关文章
- Java实现---堆排序 Heap Sort
堆排序与快速排序,归并排序一样都是时间复杂度为O(N*logN)的几种常见排序方法.学习堆排序前,先讲解下什么是数据结构中的二叉堆. 堆的定义 n个元素的序列{k1,k2,…,kn}当且仅当满足下列关 ...
- 浅谈C++之冒泡排序、希尔排序、快速排序、插入排序、堆排序、基数排序性能对比分析之后续补充说明(有图有真相)
如果你觉得我的有些话有点唐突,你不理解可以想看看前一篇<C++之冒泡排序.希尔排序.快速排序.插入排序.堆排序.基数排序性能对比分析>. 这几天闲着没事就写了一篇<C++之冒泡排序. ...
- 八大排序算法——堆排序(动图演示 思路分析 实例代码java 复杂度分析)
一.动图演示 二.思路分析 先来了解下堆的相关概念:堆是具有以下性质的完全二叉树:每个结点的值都大于或等于其左右孩子结点的值,称为大顶堆:或者每个结点的值都小于或等于其左右孩子结点的值,称为小顶堆.如 ...
- 排序算法(三)堆排序及有界堆排序Java实现及分析
1.堆排序基数排序适用于大小有界的东西,除了他之外,还有一种你可能遇到的其它专用排序算法:有界堆排序.如果你在处理非常大的数据集,你想要得到前 10 个或者前k个元素,其中k远小于n,它是很有用的. ...
- Javascript中的冒泡排序,插入排序,选择排序,快速排序,归并排序,堆排序 算法性能分析
阿里面试中有一道题是这样的: 请用JavaScript语言实现 sort 排序函数,要求:sort([5, 100, 6, 3, -12]) // 返回 [-12, 3, 5, 6, 100],如果你 ...
- 9, java数据结构和算法: 直接插入排序, 希尔排序, 简单选择排序, 堆排序, 冒泡排序,快速排序, 归并排序, 基数排序的分析和代码实现
内部排序: 就是使用内存空间来排序 外部排序: 就是数据量很大,需要借助外部存储(文件)来排序. 直接上代码: package com.lvcai; public class Sort { publi ...
- STL堆排序&时间复杂度分析
1. 逻辑&时间复杂度分析 pop 和 initialize 的时间复杂度请参考: [DSAAinC++] 大根堆的pop&remove&initialize 将数组初始化为一 ...
- 堆排序与优先队列——算法导论(7)
1. 预备知识 (1) 基本概念 如图,(二叉)堆是一个数组,它可以被看成一个近似的完全二叉树.树中的每一个结点对应数组中的一个元素.除了最底层外,该树是完全充满的,而且从左向右填充.堆的数组 ...
- 堆排序(python实现)
堆排序是利用最大最或最小堆,废话不多说: 先给出几个概念: 二叉树:二叉树是每个节点最多有两个子树的树结构.通常子树被称作“左子树”(left subtree)和“右子树” 完全二叉树:除最后一层外, ...
随机推荐
- 转载文章——Hadoop学习
转载地址:http://www.iteye.com/blogs/subjects/zy19982004?page=2 一.Hadoop社区版和发行版 社区版:我们把Apache社区一直开发的Hadoo ...
- 【转】最流行的编程语言JavaScript能做什么?
本文转自互联网! 首先很遗憾的一点是,“PHP虽然是最好的语言”,但是它不是最流行的语言. 对不起的还有刚刚在4月TIOBE编程语言排行榜上榜的各个语言: 你们都很棒,但是你们都担当不了这个大任. 开 ...
- Eos开发——构造查询条件
1.ajax 方式 var data = { orgid :orgid,year:year ,month: month,type:type,sortField:'sellEmpname' ,sortO ...
- Linux下的SVN服务器搭建
Linux下的SVN服务器搭建 鉴于在搭建时,参考网上很多资料,网上资料在有用的同时,也坑了很多人 本文的目的,也就是想让后继之人在搭建svn服务器时不再犯错,不再被网上漫天的坑爹作品所坑害,故此总 ...
- Spark——SparkContext简单分析
本篇文章就要根据源码分析SparkContext所做的一些事情,用过Spark的开发者都知道SparkContext是编写Spark程序用到的第一个类,足以说明SparkContext的重要性:这里先 ...
- .net core ClaimsPrincipal Class
hClaimsPrincipal Class ttps://msdn.microsoft.com/en-us/library/system.identitymodel.services.claimsp ...
- freeswitch 使用mysql替换默认的sqlite
转自 80000hz.com freeswitch 使用mysql替换默认的sqlite No Reply , Posted in 默认分类 on January 14, 2014 目标使用mysql ...
- Ajax语法浅析
Ajax是目前很普遍的一门技术,也是很值得探讨和研究的一门技术.本文将针对Ajax的发展过程并结合其在不同库框架中的使用方式来和大家分享下Ajax的那些新老语法. Ajax简介 Ajax全称为“Asy ...
- PAT 1045. 快速排序(25)
著名的快速排序算法里有一个经典的划分过程:我们通常采用某种方法取一个元素作为主元,通过交换,把比主元小的元素放到它的左边,比主元大的元素放到它的右边. 给定划分后的N个互不相同的正整数的排列,请问有多 ...
- Java GC系列
一个国外站点的Java JVM调优系列 下面是国内站点翻译的 http://www.importnew.com/1993.html