学习笔记--- 比较排序之堆排序

堆排序是一种集合了插入排序与归并排序的优点的排序算法,即有不错的渐近运算上限,又不用占用额外的运行空间。简单的说,它的排序思想如下:从一个数组中选出最大的数,然后在剩余的数里选出最大的数,如此循环,直到数组被穷尽,即可得到有序的数组。

根据这个思路,很容易想到其复杂度:第一步,从n个数里选出最大的数,需要比较n-1次;第二步,从n-1个数里选出最大的数,比较n-2次……那么总共需要比较的次数为:(n-1)+(n-2)+(n-3)+...+2 = O(n^2)。这与插入排序的复杂度并无区别。

而堆排序之所以能够打破这个界限,关键在于它引用的“二叉堆”的概念。

所谓“二叉堆”,就是将一个数组,按照从左到右,从上到下的顺序,将每个元素填入一个二叉树所形成的数据结构。

【此处应有示意图】

接着就可以引入很重要的“最大堆”的概念:“最大堆”表示这样一个二叉堆:任意节点的值总不小于其子节点的值。

而堆排序的主要步骤可以分为三步:

1 将给定的数组经过变换得到一个最大堆。

2 将最大堆的根节点(即最大的数)与末尾的数互换,然后对除了最后一个节点以外的新二叉堆进行维护以形成一个新的最大堆。

3 对剩下的数重复第二步,直到将数组穷尽为止。

第2,3步也就是上面所讲的排序思想的实现。而堆排序的关键在于,经过了第一步的调整之后,接下里你从n个数里找出最大的数不需要再比较n次,而只需要比较lg n次即可。因此第2,3步只需n lg n次运算即可结束。同时可以证明,将任意数组重构成一个最大堆只需要O(n)的运行时间,因此总的运行时间为O(n lg n)。

算法的实现首先需要构架一个维护最大堆的算法heapBuilder,它的作用在于,如果一个节点的左右子树均为最大堆,这个算法将调整这个节点的位置,使得包括这个节点在内的新的二叉堆成为一个最大堆。

第二步构建一个实现二叉堆的算法buildHeap,这个算法通过由下至上,对数组的每个元素执行heapBuilder过程,可以使任意数组成为一个最大堆。

这样就完成了第一步,接下来只需要构建一个完成第三步的过程即可。

以下是简单的JS实现:

function heapBuilder(arr, i){
    var left = 2*i+1;
    var right = 2*i+2;
    var largest;
	if(arr[left]>arr[i]&&arr[left]!=undefined)
		largest = left;
	else
		largest = i;
	if(arr[right]>arr[largest]&&arr[right]!=undefined)
		largest = right;
	if(largest != i) {
		[arr[i],arr[largest]] = [arr[largest],arr[i]];
		heapBuilder(arr, largest);
	}
	return arr;
}

function buildHeap(arr){
  var bound = Math.floor(arr.length/2);
  for(var i=bound;i>=0;i--)
    heapBuilder(arr, i);
  return arr;
}

function final(arr){
  var temp = buildHeap(arr);
  var result = [];
  for(i=temp.length;i>0;i--){
    [temp[i-1],temp[0]] = [temp[0],temp[i-1]];
    result.push(temp.pop());
    heapBuilder(temp, 0);
  }
  return result;
}

待续……

时间: 2024-08-05 06:13:11

学习笔记--- 比较排序之堆排序的相关文章

【算法导论】学习笔记——第6章 堆排序

堆这个数据结构应用非常广泛,数字图像处理的算法里也见过.似乎记得以前老师上课说需要用树结构实现堆排序,看了一下算法导论才明白其精髓.堆虽然是一棵树,但显然没必要非得用树结构实现堆排序.堆排序的性质很好,算法时间复杂度为O(nlgn). 1. 堆排序的简要说明.二叉堆可以分为两种形式:最大堆和最小堆.在最大堆中,最大堆性质是指除了根以外的所有结点i都要满足: A[PARENT(i)] >= A[i]:在最小堆中,最小堆性质是指除了根以外的所有结点i都要满足: A[PARENT(i)] <= A[

算法(第四版)学习笔记之java实现堆排序

继上一篇实现基于堆的优先队列后,这次将利用上一次完成的基于堆的能够重复删除最大元素操作的优先队列来实现一种经典而优雅的排序算法,称之为堆排序. 堆排序可分为两个阶段: 1.构建堆:在堆的构建过程中,我们将原始数组重新组织安排进一个堆中: 2.下沉排序:从堆中按递减顺序取出所有元素并得到排序结果 具体的思想在下面的代码中有较为详细的注释: /** * * @author seabear * */ public class HeapSort { /** * 1.构造大根堆:与上一篇基于堆的优先队列相

数据结构学习笔记06排序 (快速排序、表排序)

1.快速排序 不稳定 分而治之 找主元pivot,小于主元划分为一个子集,大于主元的划分为一个子集 然后进行递归 最好情况:每次主元正好中分,T(N) = O( NlogN ) 选主元 的方法有很多,这里用 取头.中.尾的中位数. 直接选A[0]为pivot,时间复杂度T ( N ) = O( N ) + T ( N–1 ) = O( N ) + O ( N–1 ) + T( N–2 ) = = O( N ) + O ( N–1 ) + …+ O( 1 ) = O( N^2 ) 随机取pivot

SQLCookbook 学习笔记 结果排序

select name from emp order by salary; ORDER BY 默认是按照升序排列, 当需要倒序时 用 ORDRE BY salary DESC ORDER BY  不一定要基于列名 ,也可以用数字表示 基于第几列: select name from emp order by 3;         salary是从左到右第三列. 按照多个字段排序 select * from emp order by depno, salary desc; 按照部门升序,在部门内部按

JAVA学习笔记-二分法排序(增强for循环)

package MyErFenPaiXu; public class Mycode { public static void main(String[] args){ int[] a ={18,63,25,46,3,0,99,1,2}; for(int j=0;j<a.length-1;j++){ //这里的意思为不断的比较,次数只要不小于5次就能遍历出想要的结果. for(int i=0;i<a.length-1-j;i++){ //遍历一次,一个大数会被移到最后的位置. if(a[i]&g

数据结构学习笔记06排序 (冒泡、插入、希尔)

前提void X_Sort ( ElementType A[], int N ) 大多数情况下,为简单起见,讨论从小大的整数排序 N是正整数 只讨论基于比较的排序(> = < 有定义) 只讨论内部排序 稳定性:任意两个相等的数据,排序前后的相对位置不发生改变 1.冒泡排序 (从小到大排序) 物理意义:大泡泡往下沉,小泡泡往上冒 每次比较相邻两个泡泡,符合条件,交换位置,每一轮比较完,最大的泡泡沉到最底下. 最好情况:顺序T = O( N )最坏情况:逆序T = O( N^2 ) 稳定 1 #i

java排序学习笔记

前面写了js的排序实现,总得玩玩java的哈. 同样,冒泡.选择.快速(这三个之前实现过也写过文章).堆排序,然后做比较. 主要遇到的难点: - -||想轻松点写个封装计时的逻辑,不想每调用一个排序就要写一个计时代码.想想,还是javascript写起来方便: java的话,我想到的方法是写一个抽象类:抽象出排序方法,实现一个排序计时方法(该方法调用了抽象排序,但在先后排序时加入计时代码[感觉像是aop操作]): 接着所有排序类都继承这个抽象类,并实现排序方法,调用的时候直接调用继承的排序计时方

《大话数据结构》学习笔记 排序

排序的严格定义:  假设含有n个记录的序列为{r1,r2,......,rn},对应的关键字分别为{k1,k2......,kn},需确定1,2,......,n的一种排列p1,p2,......,pn,使其相应的关键字 满足Kp1<=Kp2<=......Kpn关系,即使得序列成为一个按关键字有序的序列(rpq,rp2,......rpn),此操作称为排序.  排序的稳定性:内排序与外排序(根据记录是否全部放置在内存中). 根据排序中的主要操作,可以分为插入排序类(直接插入排序->希尔

[原创]java WEB学习笔记92:Hibernate学习之路-- -QBC 检索和本地 SQL 检索:基本的QBC 查询,带 AND 和 OR 的QBC,统计查询,排序,分页

本博客的目的:①总结自己的学习过程,相当于学习笔记 ②将自己的经验分享给大家,相互学习,互相交流,不可商用 内容难免出现问题,欢迎指正,交流,探讨,可以留言,也可以通过以下方式联系. 本人互联网技术爱好者,互联网技术发烧友 微博:伊直都在0221 QQ:951226918 -----------------------------------------------------------------------------------------------------------------