`
平凡的世界
  • 浏览: 9612 次
  • 性别: Icon_minigender_1
  • 来自: 南京
社区版块
存档分类
最新评论

堆排序学习

阅读更多
   学习了堆排序的思想,便试着用Java设计堆排序算法,如下即对应的堆排序方法,代码注释描述了堆排序的思想即堆排序与其他排序的不同之处:
        /**
* 堆排序使用的是最大堆,即堆中的每个节点的值都不小于其子节点的值.
* 堆排序的思想:
* 1.构建最大堆;
* 2.从最大堆中移除根节点,也就是最大值;
* 3.将最后一个节点移至根节点的位置;
* 4.一直向下筛选这个节点,直至满足最大堆的条件为止;
* 5.重复以上操作即可从大到小移除所有节点,即实现了排序.
*
* 堆排序可以直接在原数组基础之上构建最大堆,无需额外的存储空间,构建最大堆的时间复杂度为O(n*log(n)).
* 堆排序移除最大节点的时间复杂度为O(1),但是筛选节点的时间复杂度为O(log(n)),因此排序的时间复杂度为O(n*log(n)).
*
* @param array
*/

public static void heapSorting(int[] array) {
final int[] a = array;
final int length = a.length;
int p, q, r, s;
/**
* 构建最大堆.
* 此处认为数组索引0~i-1已经是最大堆,a[i]为插入的新节点,因此需要进行向上筛选直至满足最大堆的条件.
* 向上筛选即如果当前节点大于其父节点,则交换当前节点与其父节点的值,然后对父节点重复这个操作.
* 通过复制取代交换,减少复制总数,将a[i]复制到临时变量,然后在筛选时只做向下复制操作即可,在退出时将临时变量的值复制到循环结束节点,
* 这样以n+2次复制操作代替3n次复制操作.如a->b->c->d->a按照箭头方向复制时可以a<->b,b<->c,c<->d,这样需要九次复制(包含临时变量),
* 也可以先将d的值赋给临时变量,然后c->d,b->c,a->b,最后将临时变量的值赋给a即可,这样减少了复制的次数.
*/

/*for(int i = 1; i < length; i++) {
r = a[i];
//向上筛选.
for(p = i; p > 0; a[p] = a[p = q]) {
q = (p - 1) >> 1;//用数组表示最大堆是节点的根节点即为(x-1)/2
if(a[q] >= r) break;
}
a[p] = r;
}*/

/**
* 构建最大堆.
* 此处采用n/2次向下筛选代替n次向上筛选来构造最大堆,只需对非叶子节点操作即可,即索引为0~n/2-1.
*/

for(s = (length >> 1) - 1; s >= 0; s--) {
r = a[s];

//向下筛选形成新的最大堆.
//用数组表示最大堆时节点的子节点即为2x+1与2x+2,这里取2x+2即只遍历左右子节点均存在的情况.
//这里也采用了如上机制减少了复制的次数.

for(p = s, q = (p << 1) + 2; q < length; a[p] = a[p = q], q = (p << 1) + 2) {
if(a[q - 1] > a[q]) q = q - 1;
if(a[q] <= r) break;
}
//此处添加if判断是因为可能有只存在左子节点的情况,上述for循环并不包括这种情况,因此需要特殊考虑.
if(--q < length && a[q] > r) a[p] = a[p = q];
a[p] = r;
}

/**
* 从最大堆中删除根节点并复制到数组中.
* 此处认为数组索引0~last是最大堆,last+1之后的为已经排好序的元素,从最大堆中删除根节点并与索引last所在元素交换,执行向下筛选形成新的最大堆,
* 即新的最大堆索引为0~last-1,last之后的为新的已经排好序的元素,重复进行删除操作即可完成排序(last为0).
*/

for(s = length - 1; s > 0; s--) {
//交换删除根节点.
r = a[s];
a[s] = a[0];

//向下筛选形成新的最大堆.
//用数组表示最大堆时节点的子节点即为2x+1与2x+2,这里取2x+2即只遍历左右子节点均存在的情况.
//这里也采用了如上机制减少了复制的次数.

for(p = 0, q = 2; q < s; a[p] = a[p = q], q = (p << 1) + 2) {
if(a[q - 1] > a[q]) q = q - 1;
if(a[q] <= r) break;
}
//此处添加if判断是因为可能有只存在左子节点的情况,上述for循环并不包括这种情况,因此需要特殊考虑. if(--q < s && a[q] > r) a[p] = a[p = q];
a[p] = r;
}
}


下面是堆排序与快速排序的性能对比
数据量 10e5 10e6 10e7
堆排序时间: 0.01158s 0.21217s 5.63784s
快速排序时间: 0.01143s 0.12764s 1.47240s
分享到:
评论

相关推荐

    排序算法编程 堆排序 快速排序

    本主题将深入探讨四种常见的排序算法:堆排序、快速排序以及两种未在标题中明确提到但同样重要的排序方法——基数排序和计数排序。 首先,让我们详细了解一下堆排序。堆排序是一种基于比较的排序算法,利用了数据...

    ACM准备模板——堆排序模板

    学习并理解这个模板可以帮助参赛者快速地在比赛中实现堆排序,节省编程时间。 为了熟练掌握堆排序,你需要练习以下几点: 1. 理解并能手动构造堆的过程。 2. 掌握如何通过数组表示和操作堆。 3. 熟悉堆排序算法的每...

    数据结构堆排序

    此外,理解代码可以帮助我们学习如何在实际项目中灵活应用堆排序算法。 总结来说,堆排序是一种利用堆数据结构进行排序的有效方法,它包括了建堆和调整堆两个关键步骤。在C++中,堆排序可以通过自定义函数实现,如`...

    堆排序算法详细配图讲解

    通过具体的例子验证算法的正确性,并提供详细的注释说明,有助于其他开发者理解和学习堆排序算法的实现原理。 堆排序算法的效率依赖于树的高度,由于堆是完全二叉树,它的高度大约是logn。因此,堆排序的性能不会...

    C++语言的算法实现包括插入排序冒泡排序堆排序快速排序

    本文将深入探讨四种在C++中实现的常见排序算法:插入排序、冒泡排序、堆排序和快速排序。这些算法各有特点,适用于不同的场景,理解并掌握它们对于提升编程能力至关重要。 1. **插入排序**: 插入排序是一种简单的...

    学生成绩管理中实现堆排序

    总的来说,这个项目为学习者提供了一个很好的实践机会,将理论知识(堆排序、数据结构)与实际应用(成绩管理)相结合,有助于提升编程和算法设计能力。同时,通过查看源代码,我们可以深入理解堆排序的实现细节以及...

    堆排序C语言实现

    堆排序是一种基于比较的排序算法,它通过构造一个大顶堆或小顶堆来实现排序。在计算机科学中,堆通常被理解为...在"chapter6"这个文件夹中,可能包含了详细的代码示例和相关的解释,供学习者深入理解堆排序的实现细节。

    堆排序算法实例

    堆排序是一种基于比较的排序算法,它通过构造一个近似完全二叉树的堆...结合《算法导论》的理论,我们可以用VC6.0这样的开发环境编写和测试代码,理解堆排序的实现细节,并从中学习到如何在实际问题中运用这一算法。

    c语言学习之排序 数据结构 链表 堆排序 希尔排序 快速排序 递归排序

    "C语言学习之排序数据结构链表堆排序希尔排序快速排序递归排序" 本资源主要介绍了C语言中的排序算法,包括链表、堆排序、希尔排序、快速排序和递归排序等五种方法。同时,文章还提供了每种排序方法的原理、流程图和...

    堆排序 c语言 演示

    这对于学习和理解堆排序原理及其具体实现非常有帮助。同时,这种可视化的方法也有助于初学者更直观地理解堆排序的工作机制。 通过以上分析可以看出,堆排序算法在C语言中的实现并不复杂,但其效率较高,在实际应用...

    堆排序算法原理

    ### 堆排序算法原理详解 #### 一、引言 在计算机科学中,排序算法是一种重要的数据处理技术,广泛应用于...通过本文的学习,我们了解了堆排序的基本原理及其具体实现过程,有助于在实际编程中更好地应用这一算法。

    快速排序、归并排序、堆排序 并比较排序时间

    快速排序、归并排序和堆排序都是经典且高效的排序算法,它们各自具有独特的实现方式和性能特点。这篇文章将详细探讨这三个排序算法,并对比它们的时间复杂度。 首先,我们来看快速排序。快速排序由C.A.R. Hoare在...

    堆排序的学习示例

    3. **学习堆排序的demo**:在编程实践中,堆排序的代码通常包括初始化堆、构建堆、交换元素以及调整堆等部分。例如,在Python中,可以使用内置的`heapq`库来实现堆排序,也可以自定义函数来完成这个过程。通过实际...

    基数排序、堆排序、希尔排序、直接插入排序

    在`堆排序Heap_sort.cpp`中,你可以学习到如何维护堆的性质并进行相应的调整,如 sift-up 和 sift-down 操作,以实现排序。 希尔排序,又称缩小增量排序,是插入排序的一种更高效的改进版本。它通过将待排序的元素...

    堆排序递归和非递归的实现

    总的来说,这个资源提供了一个学习和实践堆排序算法的机会,涵盖了递归和非递归两种实现方式,对于理解和掌握堆排序算法有着重要的帮助。在实际应用中,根据具体场景和性能需求,可以选择适合的实现方式。

    希尔排序,冒泡排序,堆排序等各种排序算法

    本主题将详细探讨希尔排序、冒泡排序、堆排序等经典的排序算法,这些都是数据结构与算法学习中的核心内容,尤其对于北邮数据结构课程来说,理解并掌握这些排序方法至关重要。 1. **插入排序**: 插入排序是一种...

    堆排序算法 适合初学者学习(C语言)

    堆排序相关算法 输入一列数据进行堆排序 并显示每步数据交换 最后显示排序最终结果 适合初学者学习

    堆排序Demo

    在学习和实现堆排序时,需要注意以下几点: - 堆的构建可以通过上滤或下滤操作完成,上滤(sift-up)通常用于插入新元素,而下滤(sift-down)用于调整堆。 - 堆排序的时间复杂度为O(nlogn),空间复杂度为O(1),因为...

    直接插入排序 冒泡排序 快速排序 直接选择排序 堆排序 二路归并排序 C#源代码

    直接插入排序、冒泡排序、快速排序、直接选择排序、堆排序和二路归并排序是计算机科学中经典的排序算法,它们在数据处理和算法学习中占有重要地位。这些排序算法各有特点,适用场景不同,下面将逐一详细介绍,并结合...

    堆排序源代码

    ### 堆排序原理与实现 #### 一、堆排序简介 堆排序是一种基于比较的排序算法,利用...通过对提供的源代码的分析,我们不仅了解了堆排序的基本原理,还掌握了其实现细节,这对于进一步学习和掌握排序算法具有重要意义。

Global site tag (gtag.js) - Google Analytics