vlambda博客
学习文章列表

选择排序之——堆排序

堆排序属于选择排序,其思想是在当前选择最大(或最小)元素,放置到堆顶。


堆的定义

 ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄

堆的定义:n个元素的序列{k1,k2,,kn}当且仅当满足下列关系时,称为堆:

小堆

或者大堆

选择排序之——堆排序


由此可知,可以用完全二叉树结构来理解堆的操作。


例:{96,83,27,38,11,09}是一个堆

选择排序之——堆排序


堆排序的过程

 ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄

1将待排序序列中的n个元素构造成堆,并输出堆顶元素;

2、将剩余的n-1个元素序列重新建成一个堆,再输出堆顶元素;

3、重复第二步,直至堆中没有元素。



实现堆排序需要解决2个问题

 ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄

1、如何从一个无序的序列建立一个堆;

2、如何在输出堆顶元素后,调整剩余元素为一个新的堆。



例:将序列(49,38,65,97,76,13,27,49)构造成一个堆,输出堆顶元素,并调整余下的元素为新堆

下面以构建小堆为例,说明构造的过程

首先:根据序列构造一个完全二叉树,如下:

选择排序之——堆排序

第一步:从后往前搜索,找到第一个非叶子结点97,分别将其左右孩子结点与该结点的关键字比较,如果不满足小堆的条件,则将该结点元素与较小关键字的孩子结点元素交换。如下,将97与其左孩子结点49交换:

选择排序之——堆排序

第二步,依次向前,看下一个非叶子结点65,将其与左孩子结点13交换:

选择排序之——堆排序

第三步,继续向前,看下一个非叶子结点38,由于其左右孩子结点都比38大,不用交换

第四步,继续向前,看下一个非叶子结点49,并将其与右孩子结点13交换。注意到这里交换后,如下:

选择排序之——堆排序

注意到这里交换后,如下:

选择排序之——堆排序

此时的结点49,与其左右孩子关键字的大小关系不满足小堆的条件因此需要进一步交换,将4927交换。最后得到的小堆如下:

选择排序之——堆排序


这是一趟排序后的结果,输出13后,剩余元素调整成一个新堆过程如下

输出堆顶元素后,将序列的最后一个元素放到第一个位置,使这个序列仍然保持为完全二叉树形式:


选择排序之——堆排序

选择排序之——堆排序

再使该序列构造成堆,此过程与上同,最后构造出来的堆如下:


输出堆顶元素,重复如此操作,即可实现堆排序。


学海无涯,欢迎来稿!