堆排序算法(堆排序算法实现,形成一个小堆)

本篇文章给大家谈谈堆排序算法,以及堆排序算法实现,形成一个小堆对应的知识点,希望对各位有所帮助,不要忘了收藏本站喔。

本文目录一览:

数据结构与算法--堆和堆排序

堆排序是一种原地的、时间复杂度为 O(nlogn) 的排序算法。

堆是一种特殊的树。悄带野

只要满足这两点,它就是一个堆:

对于每个节点的值都大于等于子树中每个节点值的堆,我们叫做 “大顶堆” 。对于每个节点的值都小于等于子树中每个节点值的堆,我们叫做 “小顶堆” 。

完全二叉树比较适合用数组来存储。用数组来存储完全二叉树是非常节省存储空间的。下标可以直接计算出左右字数的下标。(数组中下标为 i 的节点,左子节点下标为 i∗2 ,右子节点下标为 i∗2+1,父节点的下标为 i/2 。)

如果我们把新插入的元素放到堆的最后,你可以看我画的这个图,是不是不符合堆的特性了?于是,我们就需要进行调整,让其重新满足堆的行贺特性,这个过程我们起了一个名字,就叫做 堆化(heapify) 。

堆化实际上有两种,从下往上和从上往下。这里我先讲从下往上的堆化方法。

堆化非常简单,就是顺着节点所在的路径,向上或者向下,对比,然后交换。

我们把最后一个节点放到堆顶,然后利用同样的父子节点对比方法。对于不满足父子节点大小关系的,互换两个节点,并且重复进行这个过程,直到父子节点之间满足大小关系为止。这就是 从上往下的堆化方法 。

一个包含 n 个节点的完全二叉树,树的高度不会超过 log2n。堆化的过程是顺着节点所在路径比较交换的,所以堆化的时间复杂度跟树的高度成正比,也就是 O(logn)。插入数据和删除堆顶元素的主要逻辑就是堆化,所以,往堆中插入一个元素和删除堆顶元素的时间复杂度都是 O(logn)。

这里我们借助于堆这种数据结构实现的排序算法,就叫做堆排序。这种排序方法的时间复杂度非常稳定,是 O(nlogn),并且它还是原地排序算法。

从后往前处理数组,并且每个数据都是从上往下堆化。

因为叶子节点往下堆化只能自己跟自己比较,所以我们直接从最后一个非叶子节点开始,依次堆化就行了。

建堆的时间复杂度就是 O(n)。 推导过程见 极客时间--数据结构与算法之美

建堆结束之后,数组中的数据已经是按照大顶堆的特性来组织的。数组中的第一个元素就是堆顶,也就是最大的元素。我们把它跟最后一个元素交换,那最大元素就放到了下标为 n 的位置。

这个过程有点类似上面讲的“删除堆顶元素”的操作,当堆顶元素移除之后,我们把下标为 n 的元素放到堆顶,然后再通过堆化的方法,将剩下启喊的 n−1 个元素重新构建成堆。堆化完成之后,我们再取堆顶的元素,放到下标是 n−1 的位置,一直重复这个过程,直到最后堆中只剩下标为 1 的一个元素,排序工作就完成了。

整个堆排序的过程,都只需要极个别临时存储空间,所以堆排序是原地排序算法。堆排序包括建堆和排序两个操作,建堆过程的时间复杂度是 O(n),排序过程的时间复杂度是 O(nlogn),所以,堆排序整体的时间复杂度是 O(nlogn)。

堆排序不是稳定的排序算法,因为在排序的过程,存在将堆的最后一个节点跟堆顶节点互换的操作,所以就有可能改变值相同数据的原始相对顺序。

堆这种数据结构几个非常重要的应用:优先级队列、求 Top K 和求中位数。

假设我们有 100 个小文件,每个文件的大小是 100MB,每个文件中存储的都是有序的字符串。我们希望将这些 100 个小文件合并成一个有序的大文件。这里就会用到优先级队列。

这里就可以用到优先级队列,也可以说是堆。我们将从小文件中取出来的字符串放入到小顶堆中,那堆顶的元素,也就是优先级队列队首的元素,就是最小的字符串。我们将这个字符串放入到大文件中,并将其从堆中删除。然后再从小文件中取出下一个字符串,放入到堆中。循环这个过程,就可以将 100 个小文件中的数据依次放入到大文件中。

我们可以用优先级队列来解决。我们按照任务设定的执行时间,将这些任务存储在优先级队列中,队列首部(也就是小顶堆的堆顶)存储的是最先执行的任务。

如何在一个包含 n 个数据的数组中,查找前 K 大数据呢?我们可以维护一个大小为 K 的小顶堆,顺序遍历数组,从数组中取出数据与堆顶元素比较。如果比堆顶元素大,我们就把堆顶元素删除,并且将这个元素插入到堆中;如果比堆顶元素小,则不做处理,继续遍历数组。这样等数组中的数据都遍历完之后,堆中的数据就是前 K 大数据了。

中位数,顾名思义,就是处在中间位置的那个数。

使用两个堆:一个大顶堆, 一个小顶堆。 小顶堆中的数据都大于大顶堆中的数据。

如果新加入的数据小于等于大顶堆的堆顶元素,我们就将这个新数据插入到大顶堆;否则,我们就将这个新数据插入到小顶堆。

也就是说,如果有 n 个数据,n 是偶数,我们从小到大排序,那前 2n 个数据存储在大顶堆中,后 2n 个数据存储在小顶堆中。这样,大顶堆中的堆顶元素就是我们要找的中位数。如果 n 是奇数,情况是类似的,大顶堆就存储 2n+1 个数据,小顶堆中就存储 2n 个数据。

极客时间--数据结构与算法之美--28 | 堆和堆排序:为什么说堆排序没有快速排序快?

[img]

堆排序过程

1,实用的排序算法:选择排序

(1)选择排序的基本思想是:每一趟(例如第i趟,i=0,1,2,3,……n-2)在后面n-i个待排序元素中选择排序码最小的元素,作为有序元素序列的第i个元素。待到第n-2趟做完,待排序元素只剩下一个,就不用再选了。

(2)三种常用的选择排序方法

1直接选择排序

2锦标赛排序

3堆排序

其中,直接排序的思路和实现都比较简单,并且相比其他排序算法,直接选择排序有一个突出的优势——数据的移动次数少。

(3)直接选择排序简介

1直接选择排序(select sort)是一种简单的排序方法,它的基本步骤是:

1)在一组元素V[i]~V[n-1]中选择具有最小排序码的元素;

2)若它不是这组元素中的第一个元素,则将它与这组元素中的第一个元素对调;

3)在这组元素中剔除这个具有最小排序码的元素,在剩下的元素V[i+1]~V[n-1]中重复执行1、2步骤,直到剩余元素只有一个为止。

2直接选择排序使用注意

它对一类重要的元素序列具有较好的效率,这就是元素规模很大,而排序码却比较小的序列。因为对这种序列进行排序,移动操作所花费的时间要比比较操作的时间大的多,而其他算法移动操作的次数都要比直接选择排序来的多,直接选择排序是一种不稳定的 排序方法。

3直接选择排序C++函数代码

//函数功能,直接选择排序算法对数列排序

//函数参数,数列起点,数列终点

void dselect_sort(const int start, const int end) {

for (int i = start; i end; ++i) {

int min_position = i;

for (int j = i + 1; j = end; ++j) { //此循环用来寻找最小关键码

if (numbers[j] numbers[min_position]) {

min_position = j;

}

}

if (min_position != i) { //避免自己与自己交换

swap(numbers[min_position], numbers[i]);

(4)关于锦标赛排序

直接选择排序中,当n比较大时,排序码的比较次数相当多,这是因为在后一趟比较选择时,往往把前一趟已经做过的比较又重复了一遍,纯竖伏没有把前一趟的比较结果保留下来。

锦标赛排序(tournament sort)克服了这一缺点。它的思想与体育比赛类似,就是把待排序元素两两进行竞赛,选出其中的胜利者,之后胜利者之间继续竞赛纤仿,再选出其中的胜利者,然后重复这一过程,最终构造出胜者树,从而实现排序的目的。

2,堆排序的排序过程

(1)个人理解:堆排序是选择排序的一种,所以它也符合选择排序的整体思想。直接选择排序是在还未成序的元素中逐个比较选择,而堆排序是首先建立一个堆(最大堆或最小堆),这使得数列已经“大致”成序,之后只需要局部调整来重建堆即可。建立堆及重建堆这一过程映射到数组中,其实就是一个选择的过程,只不过不是逐个比较选择,而是借助完全二叉树来做到有目的的比较选择。这也是堆排序性能优于直接选择排序的一个体现。

(2)堆排序分为两个步骤:

1根据初始输入数据,利用堆的调整算法形成初始堆;

2通过一系列的元素交换和重新调整堆进行排序。

(3)堆排序的排序思路

1前提,我们是要对n个数据进行递增排序,也就是说拥有最大排序码的元素应该在数组的末端。

2首先建立一个最大堆,则堆的第一个元素heap[0]具有最大的排序码,将heap[0]与heap[n-1]对调,把具有最大排序码的元素交换到最后,再对前面n-1个元素,使用堆的调整算法siftDown(0,n-2),重新建立最大堆。结果具有次最大排序码的元素又浮到堆顶,即heap[0]的位置,再对调heap[0]与heap[n-2],并调用siftDown(0,n-3),对前n-2个元素重新调整,……如此反复,最后得到一个数列的排序码递增序列。

(4)堆排序的排序过程:

下面给出局做携部调整成最大堆的函数实现siftDown(),这个函数在前面最小堆实现博文中的实现思路已经给出,只需做微小的调整即可用在这里建立最大堆。

堆排序是什么

【概念】堆排序(Heapsort)是指利用堆积树(堆)这种数据结构所设计的一种排序算法,它是选择排序的一种。可以利用数组的特点快速定位指定索引的元素。堆分为大根堆和小根堆,是完全二叉树。大根堆的要求是每个节点的值都不大于其父节点的值,即A[PARENT[i]]

=

A[i]。在数组的非降序排序中,需要使用的就是大根堆,因为根据大根堆的要求可知,最大的值一定在堆顶。

【起源】

1991年的计算机先驱奖获得者、斯坦福大学计算机科学系教授罗伯特·弗洛伊德(Robert

W.Floyd)和威廉姆斯(J.Williams)在1964年共同发明了著名的堆排序算法(

Heap

Sort

)。

【简介】

堆排序利用了大根堆(或小根堆)堆顶记录的关键字最大(或最小)这一特征,使得在当前无序区中选取最大(或最小)关键字的记录变得简单。

(1)用大根堆排序的基本思想

先将初始文件R[1..n]建成一个大根堆,此堆为初始的无序区

再将关键字最大的记录R[1](即堆顶)和无序区的最后一个记录R[n]交换,由此得到新的无序区R[1..n-1]和有序区R[n],且满足R[1..n-1].keys≤R[n].key

③由于交换后新的根R[1]可能违反堆性质,故应将当前无序区R[1..n-1]调整为堆。然后再次将R[1..n-1]中关键字最大的记录R[1]和该区间的最后一个记录R[n-1]交换,由此得到新的无序区R[1..n-2]和有序区R[n-1..n],且仍满足关系R[1..n-2].keys≤R[n-1..n].keys,同样要将R[1..n-2]调整为堆。

……

直到无序区只有一个元素为止。

(2)大根堆排序算法的基本操作:

①建堆,建堆是不断调整堆的过程,从len/2处开始调整,一直到第一个节点,此处len是堆中元素的个数。建堆的过程是线性的过程,从len/2到0处一直调用调整堆的过程,相当于o(h1)+o(h2)…+o(hlen/2)

其中h表示节点的深度,len/2表示节点的个数,这是一个求和的过程,结果是线性的O(n)。

②调整堆:调整堆在构建堆的过程中会用到,而且在堆排序过程中也会用到。利用的思想是比较节点i和它的孩子节点left(i),right(i),选出三者最枝弯让大(或者最小)者,如果猛局最大(小)值不是节点i而是它的一个孩子节点,那边交互节点i和该节点,然后再调用调整堆过程,这是一个递归的过程。调整堆的过程时间复杂度与堆的深度有关系,是lgn的操作,因为闹散是沿着深度方向进行调整的。

③堆排序:堆排序是利用上面的两个过程来进行的。首先是根据元素构建堆。然后将堆的根节点取出(一般是与最后一个节点进行交换),将前面len-1个节点继续进行堆调整的过程,然后再将根节点取出,这样一直到所有节点都取出。堆排序过程的时间复杂度是O(nlgn)。因为建堆的时间复杂度是O(n)(调用一次);调整堆的时间复杂度是lgn,调用了n-1次,所以堆排序的时间复杂度是O(nlgn)[2]

注意:

①只需做n-1趟排序,选出较大的n-1个关键字即可以使得文件递增有序。

②用小根堆排序与利用大根堆类似,只不过其排序结果是递减有序的。堆排序和直接选择排序相反:在任何时刻堆排序中无序区总是在有序区之前,且有序区是在原向量的尾部由后往前逐步扩大至整个向量为止

【特点】

堆排序(HeapSort)是一树形选择排序。堆排序的特点是:在排序过程中,将R[l..n]看成是一棵完全二叉树的顺序存储结构,利用完全二叉树中双亲结点和孩子结点之间的内在关系(参见二叉树的顺序存储结构),在当前无序区中选择关键字最大(或最小)的记录

【算法分析】

堆排序的时间,主要由建立初始堆和反复重建堆这两部分的时间开销构成,它们均是通过调用Heapify实现的。

平均性能:O(N*logN)。

其他性能:由于建初始堆所需的比较次数较多,所以堆排序不适宜于记录数较少的文件。堆排序是就地排序,辅助空间为O(1)。它是不稳定的排序方法。(排序的稳定性是指如果在排序的序列中,存在前后相同的两个元素的话,排序前

和排序后他们的相对位置不发生变化)。

堆和堆排序

1,堆是一个完全二叉树;

完全二叉树要求除了最后一层,其他层的节点都是满的,最后一层的节点都靠左排列。

2,堆中每个节点都必须大于等于(或小于等于)其子树中每个节点的值。

堆中每个节点的值都大于等于(或者小于等于)其左右子节点的值。

3,对于每个节点的值都大于等于子树中每个节点值的堆,叫作“大顶堆”。对于每个节点的值都小于等于子树中每个节点值的堆,梁祥唯叫“小顶堆”。

要实现一个堆,要先知道堆都支持哪些操作,已及如何存储一个堆。

1,如何存储一个堆:

完全二叉树比较适合用数组来存储。用数组来存储完全二叉树是非常节省存储空间的。因为不需要存储左右子节点的指针,单纯地通过数组的下标,就可以找到一个节点的左右子节点和父节点。

2,往堆中插入一个元素

往堆中插入一个元素后,需要继续满足堆的两个特性

(1)如果把新插入的元素放到堆的最后,则不符合堆的特性了,于是需要进行调整,让其重新满足堆的特性,这个过程叫做 堆化(heapify)

(2)堆化实际上有两种,从下往上和从上往下

(3)从下往上的堆化方法:

堆化非常简单,就是顺着节点所在的路径,向上或者向下,对比,然后交换。

(1)从堆的定义的第二条中,任何节点的值都大于等于(或小于等于)子树节点的值,则堆顶元素存储的就是堆中数据的最大值或最小值。

(2)假设是大顶堆,堆堆顶元素就是最大的元素,但删除堆顶元素之后,就需要把第二大元素放到堆顶,那第二大元素肯定会出现在左右子节点中。然后在迭代地删除第二大节点,以此类推,直到叶子节点被删除。

但这种方式会使堆化出来的堆不满足完全二叉树的特性

(3)可以把最后一个节点放到堆顶,然后利用同样的父子节点对比方法,对于不满足父子节点大小关系的,互换两个节点,并且重复进行这个过程,直到父子节点之间满足大小关系为止,这是从上往下的堆化方法。

一个包含n个节点的完全二叉树,树的高度不会超过log2n。堆化的过程是顺着节点所在路径比较交换的,所以堆化的时间复杂度跟树的高度成正比,即O(log n)。插入数据和删除堆顶元素的主要逻辑就是堆化,所以往堆中插入一个元素和删除堆顶元素的时间复杂度都是O(log n)。

(1)排序方法有时间复杂度是O(n^2)的冒泡排序,插入排序,选择排序,有时间复杂度是O(nlogn)的归并排序,快速排序,线性排序。

(2)借助堆这种数据结构实现的排序算法就叫作堆排序,这种排序方法的时间复杂度非常稳定,是O(nlogn),并且它还是原地排序算法。

堆排序的过程大致分解为两大步骤:建堆和排序

(3)建堆:

1,首先将数组原地建成一个堆。“原地”:是指不借助另一个数组,就在原地数组上操作。

2,建堆有两种思路:

第一种:在堆中插入一个元素的思路。

尽管数组中包含n个数据,但是可以假设起初堆中只包含一个数据,就是下标为1的数据。然后,调用插入方法,将将下标从2到n的数据依次插入到堆中,这样就将包含n个数据的数组,组织成了堆

第二种:是从后往前处理数组,并且每个数据都是从上往下堆化。

第二种和第橡培一种思路截然相反,第一种建堆思路的处理过程是从前往后处理数据,并且每个数据插入堆中时,都是从下往上堆化。

对下标从n/2开始到1的数据进行堆化,下标是n/2 + 1到n的节点,是叶子节点,不需堆化

3,建堆的时间复杂度

每个节点堆化的时间复杂度是O(logn),则n/2+1个节点堆化的总时间复杂度是O(n)。

①:因为叶子节点不需要堆化,所以需要堆化的节点从倒数第二层开始。每个节点堆化的过程中,宴樱需要比较和交换的节点个数,跟这个节点高度k成正比。

(4)排序:

建堆结束后,数组中的数据已是按照大顶堆的特性来组织的。数组中的第一个元素就是堆顶,也就是最大的元素。

将它和最后一个元素交换,最大元素就放到了下标为n的位置

这个过程有点类似“删除堆顶元素”的操作,当堆顶元素移除后,把下标为n的元素放到堆顶,然后在通过堆化的方法,将剩下的n-1个元素重新构建成堆。堆化完成之后,在取堆顶元素,放到下标是n-1的位置,一直重复这个过程,直到最后堆中只剩下标为1的一个元素,排序工作就完成了。

(5)时间,空间复杂度,以及稳定性分析

①:整个堆排序的过程,都只需要极个别临时存储空间,所以堆排序是原地排序算法。

②:堆排序包括建堆和排序两个操作,建堆过程的时间复杂度是O(n),排序过程的时间复杂度是O(nlogn),所以堆排序的时间复杂度是O(nlogn)

③:堆排序不是稳定的排序算法,可能改变值相等的数据原始相对顺序。

堆排序是稳定的排序算法

.example-btn{color:#fff;background-color:#5cb85c;border-color:#4cae4c}.example-btn:hover{color:#fff;background-color:#47a447;border-color:#398439}.example-btn:active{background-image:none}div.example{width:98%;color:#000;background-color:#f6f4f0;background-color:#d0e69c;background-color:#dcecb5;background-color:#e5eecc;margin:0 0 5px 0;padding:5px;border:1px solid #d4d4d4;background-image:-webkit-linear-gradient(#fff,#e5eecc 100px);background-image:linear-gradient(#fff,#e5eecc 100px)}div.example_code{line-height:1.4em;width:98%;background-color:#fff;padding:5px;border:1px solid #d4d4d4;font-size:110%;font-family:Menlo,Monaco,Consolas,"Andale Mono","lucida console","Courier New",monospace;word-break:break-all;word-wrap:break-word}div.example_result{background-color:#fff;padding:4px;border:1px solid #d4d4d4;width:98%}div.code{width:98%;border:1px solid #d4d4d4;background-color:#f6f4f0;color:#444;padding:5px;margin:0}div.code div{font-size:110%}div.code div,div.code p,div.example_code p{font-family:"courier new"}pre{margin:15px auto;font:12px/20px Menlo,Monaco,Consolas,"Andale Mono","lucida console","Courier New",monospace;white-space:pre-wrap;word-break:break-all;word-wrap:break-word;border:1px solid #ddd;border-left-width:4px;padding:10px 15px} 排序算法是《数据结构与算法》中最基本的算法之一。排序算法可以分为内部排序和外部排序,内部排序是数据记录在内存中进行排序,而外部排序是因排序的数据很大,一次不能容纳全部的排序记录,在排序过程中需要访问外存。常见的内部排序算法有:插入排序、希尔排序、选择排序、冒泡排序、归并排序、快速排序、堆排序、基数排序等。以下是堆排序算法:

堆排序(Heapsort)是指利用堆这种数据结构所设计的一种排序算法。堆积是一个近似完全二叉树的结构,并竖弊散同时满足堆积的性质:即子结点的键值或索引总是小于(或者大于)它的父节点。堆排序可以说是一种利用堆的概念来排序的选择排序。分为两种方法:

大顶堆:每个节点的值都大于或等于其子节点的值,在堆排序算法中用于升序排列; 小顶堆:每个节点的值都小于或等于其子节点的值,在堆排序算法中用于降序排列;

堆排序的平均时间复杂度为 Ο(nlogn)。

1. 算法步骤

创建一个堆 H[0……n-1];

把堆首(最大值)和堆尾互换;

把堆的尺寸缩小 1,并调用 shift_down(0),目的是卜陵把新的数组顶端余氏数据调整到相应位置;

重复步骤 2,直到堆的尺寸为 1。

2. 动图演示

代码实现 JavaScript 实例 var len ;     // 因为声明的多个函数都需要数据长度,所以把len设置成为全局变量

function buildMaxHeap ( arr ) {   // 建立大顶堆

    len = arr. length ;

    for ( var i = Math . floor ( len / 2 ) ; i = 0 ; i -- ) {

        heapify ( arr , i ) ;

    }

}

function heapify ( arr , i ) {     // 堆调整

    var left = 2 * i + 1 ,

        right = 2 * i + 2 ,

        largest = i ;

    if ( left arr [ largest ] ) {

        largest = left ;

    }

    if ( right arr [ largest ] ) {

        largest = right ;

    }

    if ( largest != i ) {

        swap ( arr , i , largest ) ;

        heapify ( arr , largest ) ;

    }

}

function swap ( arr , i , j ) {

    var temp = arr [ i ] ;

    arr [ i ] = arr [ j ] ;

    arr [ j ] = temp ;

}

function heapSort ( arr ) {

    buildMaxHeap ( arr ) ;

    for ( var i = arr. length - 1 ; i 0 ; i -- ) {

        swap ( arr , 0 , i ) ;

        len --;

        heapify ( arr , 0 ) ;

    }

    return arr ;

}

Python 实例 def buildMaxHeap ( arr ) :

    import math

    for i in range ( math . floor ( len ( arr ) / 2 ) , - 1 , - 1 ) :

        heapify ( arr , i )

def heapify ( arr , i ) :

    left = 2 *i+ 1

    right = 2 *i+ 2

    largest = i

    if left arr [ largest ] :

        largest = left

    if right arr [ largest ] :

        largest = right

    if largest != i:

        swap ( arr , i , largest )

        heapify ( arr , largest )

def swap ( arr , i , j ) :

    arr [ i ] , arr [ j ] = arr [ j ] , arr [ i ]

def heapSort ( arr ) :

    global arrLen

    arrLen = len ( arr )

    buildMaxHeap ( arr )

    for i in range ( len ( arr ) - 1 , 0 , - 1 ) :

        swap ( arr , 0 , i )

        arrLen - = 1

        heapify ( arr , 0 )

    return arr

Go 实例 func heapSort ( arr [] int ) [] int {

        arrLen := len ( arr )

        buildMaxHeap ( arr , arrLen )

        for i := arrLen - 1 ; i = 0 ; i -- {

                swap ( arr , 0 , i )

                arrLen -= 1

                heapify ( arr , 0 , arrLen )

        }

        return arr

}

func buildMaxHeap ( arr [] int , arrLen int ) {

        for i := arrLen / 2 ; i = 0 ; i -- {

                heapify ( arr , i , arrLen )

        }

}

func heapify ( arr [] int , i , arrLen int ) {

        left := 2 * i + 1

        right := 2 * i + 2

        largest := i

        if left arrLen arr [ left ] arr [ largest ] {

                largest = left

        }

        if right arrLen arr [ right ] arr [ largest ] {

                largest = right

        }

        if largest != i {

                swap ( arr , i , largest )

                heapify ( arr , largest , arrLen )

        }

}

func swap ( arr [] int , i , j int ) {

        arr [ i ], arr [ j ] = arr [ j ], arr [ i ]

}

Java 实例 public class HeapSort implements IArraySort {

    @Override

    public int [ ] sort ( int [ ] sourceArray ) throws Exception {

        // 对 arr 进行拷贝,不改变参数内容

        int [ ] arr = Arrays . copyOf ( sourceArray, sourceArray. length ) ;

        int len = arr. length ;

        buildMaxHeap ( arr, len ) ;

        for ( int i = len - 1 ; i 0 ; i -- ) {

            swap ( arr, 0 , i ) ;

            len --;

            heapify ( arr, 0 , len ) ;

        }

        return arr ;

    }

    private void buildMaxHeap ( int [ ] arr, int len ) {

        for ( int i = ( int ) Math . floor ( len / 2 ) ; i = 0 ; i -- ) {

            heapify ( arr, i, len ) ;

        }

    }

    private void heapify ( int [ ] arr, int i, int len ) {

        int left = 2 * i + 1 ;

        int right = 2 * i + 2 ;

        int largest = i ;

        if ( left arr [ largest ] ) {

            largest = left ;

        }

        if ( right arr [ largest ] ) {

            largest = right ;

        }

        if ( largest != i ) {

            swap ( arr, i, largest ) ;

            heapify ( arr, largest, len ) ;

        }

    }

    private void swap ( int [ ] arr, int i, int j ) {

        int temp = arr [ i ] ;

        arr [ i ] = arr [ j ] ;

        arr [ j ] = temp ;

    }

}

PHP 实例 function buildMaxHeap ( $arr )

{

    global $len ;

    for ( $i = floor ( $len / 2 ) ; $i = 0 ; $i -- ) {

        heapify ( $arr , $i ) ;

    }

}

function heapify ( $arr , $i )

{

    global $len ;

    $left = 2 * $i + 1 ;

    $right = 2 * $i + 2 ;

    $largest = $i ;

    if ( $left $arr [ $largest ] ) {

        $largest = $left ;

    }

    if ( $right $arr [ $largest ] ) {

        $largest = $right ;

    }

    if ( $largest != $i ) {

        swap ( $arr , $i , $largest ) ;

        heapify ( $arr , $largest ) ;

    }

}

function swap ( $arr , $i , $j )

{

    $temp = $arr [ $i ] ;

    $arr [ $i ] = $arr [ $j ] ;

    $arr [ $j ] = $temp ;

}

function heapSort ( $arr ) {

    global $len ;

    $len = count ( $arr ) ;

    buildMaxHeap ( $arr ) ;

    for ( $i = count ( $arr ) - 1 ; $i 0 ; $i -- ) {

        swap ( $arr , 0 , $i ) ;

        $len --;

        heapify ( $arr , 0 ) ;

    }

    return $arr ;

}

C 实例 #include

#include

void swap ( int * a , int * b ) {

    int temp = * b ;

    * b = * a ;

    * a = temp ;

}

void max_heapify ( int arr [ ] , int start , int end ) {

    // 建立父节点指标和子节点指标

    int dad = start ;

    int son = dad * 2 + 1 ;

    while ( son 0 ; i -- ) {

        swap ( arr [ 0 ] , arr [ i ] ) ;

        max_heapify ( arr , 0 , i - 1 ) ;

    }

}

int main ( ) {

    int arr [ ] = { 3 , 5 , 3 , 0 , 8 , 6 , 1 , 5 , 8 , 6 , 2 , 4 , 9 , 4 , 7 , 0 , 1 , 8 , 9 , 7 , 3 , 1 , 2 , 5 , 9 , 7 , 4 , 0 , 2 , 6 } ;

    int len = ( int ) sizeof ( arr ) / sizeof ( * arr ) ;

    heap_sort ( arr , len ) ;

    int i ;

    for ( i = 0 ; i

关于堆排序算法和堆排序算法实现,形成一个小堆的介绍到此就结束了,不知道你从中找到你需要的信息了吗 ?如果你还想了解更多这方面的信息,记得收藏关注本站。

标签列表