数据结构之堆排序

在数据结构中,堆排序是非常重要的一个知识点,尤其像在期末考试、考研等计算机考试中经常会考察堆排序,并要求画出示意图.下面主要通过一道考研题目讲述堆排序的知识,希望对大家有所帮助.
(文章内容参考严蔚敏的《数据结构》、王道论坛的《数据结构》和自己的一些理解)
参看动态图:http://www.benfrederickson.com/heap-visualization/

一.堆排序定义

堆排序是一种树形选择排序方法,它的特点是在排序过程中,将L[1...n]看成一颗完全二叉树的顺序存储结果,利用完全二叉树中双亲结点和孩子结点之间的内在关系,在当前无序区中选择关键字最大或最小的元素.该算法时间复杂度O(nlong2n),是不稳定排序.
堆的定义:n个元素的序列K[1..n]当且仅当满足:
(1).K[i]<=K[2i]且K[i]<=K[2i+1]  或 (2).K[i]>=K(2i)且K[i]>=K[2i+1] (i=1,2...|_n/2_|)
如下图所示:

满足(1)的堆称为小根堆,满足(2)的堆称为大根堆.
在大根堆中,堆顶元素(完全二叉树的根)必为序列中n个元素的最大值,且对其任一非根结点,它的值不大于其双亲结点值.对应的是最大堆.同理,小根堆定义相反,根节点为最小值.如下图分别是最大堆和最小堆.堆采用的存储方式是顺序存储结构.

二.堆排序实现

堆排序利用堆的特性进行排序,其基本思想是:首先将待排序的记录序列构造成一个堆;然后选出对中所有记录的最小值(最小堆);再把它从堆中输出,并把剩余的元素排成最小堆,依次找次小的记录并输出,直到只有一个记录为止.问题的步骤为:
(1).如何从一个无序序列初始建堆,这是堆排序的关键.(初始建堆)
(2).如何处理堆顶记录.(处理堆顶)
(3).输出堆顶元素后如何调整剩余元素,构建一个新堆.(重新建堆)

例:(改考研题)使用堆排序对序列{38,49,13,97,27,76,65,50}进行排序,要求画出最小堆,并画出堆排序的示意图.
首先按照题目顺序构造一个完全二叉树如下图所示,然后按照下面的"初始建堆"和"堆排序"实现.

1.初始建堆

对初始序列建堆,就是有一个反复筛选的过程.n个结点的完全二叉树,最后一个结点是第|_n/2_|(其中|_x_|表示不大于x的最大整数)个结点的孩子.小根堆其基本思想从|_n/2_|根节点开始,尽量让最小数向二叉树根结点(堆顶)移动,使子树都成为堆.
(1).对第|_n/2_|个结点为根的子树筛选,对于小根堆:如果根结点的关键字大于左右子女结点中关键字较小者,则交换,使子树成为堆.
题中:i=|_8/2_|=4,指向97根结点,大于其左孩子结点50,故交换顺序.如下图.

(2).然后向前依次对各结点(|_n/2_|-1到1)为根的子树进行筛选,看该结点值是否小于其左右子结点,如果不是,将左右子结点中较小者与之交换;交换后可能会破坏下一级的堆,继续采用上述方法构造下一级的堆,直到该结点为根的子树构成堆位置.

  

(3).反复使用上述方法建堆,直到根节点.题中根节点交换时亦要检查器下级堆是否要交换顺序.

2.堆排序

在使用完全二叉树初始建立好如上图的最小堆后,就是对该堆进行排序输出.此时的算法是:

(1).输出堆顶元素,题中堆顶元素=13;输出后以堆中最后一个元素=97替代堆顶元素;然后将根节点值与左右子树的根节点进行比较,并与其中小者进行交换;

(2).重复上述操作,直到叶子节点,将得到的新堆称为这个从堆顶至叶子的调整过程为"筛选".
输出堆顶27,将最后一个元素65替代堆顶元素,再从49和38中选择较小值38,将65与38元素交换.(答题是只画最后交换好的再配上必要文字说明即可)

输出堆顶38,将最后一个元素76替代堆顶元素,再根据方法依次交换76与49,76与50.

输出堆顶49,将最后一个元素97替代堆顶元素,再根据方法依次交换97与50,97与76.

同理一次输出如下:

三.总结

该文章主要是解决上面的那个堆排序问题,而相应的算法代码和插入删除亦类似没给出.写这篇文章主要是纪念自己这几个月考研的日子,同时无论考研结果如何,都要在考完后学习更多自己感兴趣的编程知识,并完成一些自己感兴趣的工程和博客.这才是我想要的东西.最后希望该文章对大家有所帮助,尤其是考研的学子.希望大家考研顺利,同时如果文章中有错误或不足之处,希望大家海涵!

(BY:Eastmount 2013-12-17 下午4点 http://blog.csdn.net/eastmount/)

 

时间: 2024-11-02 11:40:15

数据结构之堆排序的相关文章

数据结构示例——堆排序过程

完整算法见[例程],本文用一个例子,演示堆排序的过程. 例:对{57, 40, 38, 11, 13, 34, 48, 75, 6, 19, 9, 7}进行堆排序的过程. 算法如下: void HeapSort(RecType R[],int n) { int i; RecType temp; //(1)循环建立初始堆 for (i=n/2; i>=1; i--) sift(R,i,n); //(2)进行n-1次循环,完成推排序 for (i=n; i>=2; i--) { temp=R[1]

数据结构中堆排序问题求助

问题描述 数据结构中堆排序问题求助 求解七八九题,答案给的分别是D D D求详细的解法,谢谢了 解决方案 第三题,过程---- 解决方案二: 0,1,6,7,选择完毕之后,只能从2,3里选吧,8有指向它的一个结点啊!!!根据规则不能选- 解决方案三: 数据结构堆排序[数据结构]堆排序[数据结构]堆排序 解决方案四: 其实我觉得你应该去考研论坛问问,或者王道论坛- 解决方案五: http://www.zybang.com/question/bd19e13f1f057532f3e52127d6ebb

c#代码-求高手解答二进制堆及其应用问题

问题描述 求高手解答二进制堆及其应用问题 2.二进制堆及其应用 [问题描述] 堆是设计很巧妙的数据结构,堆排序的算法也有很多应用.但当堆比较庞大时,选取堆顶元素及重新建堆的工作量也较大.利用堆的定义构建二进制堆,应用于优先队列有很大的优势.二进制堆是在二进制树Bk上建立的数据结构.一个整数可以表示为二进制数,一组关键字组成的序列可以由一组二进制堆表示. [设计要求] 设计二进制堆的抽象数据类型及其实现. (1)实现二进制堆Hk的ADT. (2)实现二进制堆的简单应用. 以上是我的作业题,我没看懂

结构之美——优先队列基本结构(四)——二叉堆、d堆、左式堆、斜堆

实现优先队列结构主要是通过堆完成,主要有:二叉堆.d堆.左式堆.斜堆.二项堆.斐波那契堆.pairing 堆等.   1. 二叉堆  1.1. 定义 完全二叉树,根最小. 存储时使用层序.   1.2. 操作 (1). insert(上滤) 插入末尾 26,不断向上比较,大于26则交换位置,小于则停止.   (2). deleteMin(下滤) 提取末尾元素,放在堆顶,不断下滤:   (3). 其他操作: 都是基于insert(上滤)与deleteMin(下滤)的操作. 减小元素:减小节点的值,

浅谈算法和数据结构 五 优先级队列与堆排序

在很多应用中,我们通常需要按照优先级情况对待处理对象进行处理,比如首先处理优先级最高的对象,然后处理次高的对象.最简单的一个例子就是,在手机上玩游戏的时候,如果有来电,那么系统应该优先处理打进来的电话. 在这种情况下,我们的数据结构应该提供两个最基本的操作,一个是返回最高优先级对象,一个是添加新的对象.这种数据结构就是优先级队列(Priority Queue) . 本文首先介绍优先级队列的定义,有序和无序数组以及堆数据结构实现优先级队列,最后介绍了基于优先级队列的堆排序(Heap Sort) 更

数据结构例程——选择排序之堆排序

本文是[数据结构基础系列(9):排序]中第7课时[选择排序之堆排序]的例程. 对算法运行过程,补充了一个示例,见[补充示例]. #include <stdio.h> #define MaxSize 20 typedef int KeyType; //定义关键字类型 typedef char InfoType[10]; typedef struct //记录类型 { KeyType key; //关键字项 InfoType data; //其他数据项,类型为InfoType } RecType;

数据结构和算法16 之堆排序

   堆排序,顾名思义就是利用堆这个数据结构对数据项进行排序,前面提到过,堆数据结构中,节点大于或等于自己的子节点.那么我们可以将待排序的数据项依次添加到堆中,然后再依次取出根节点即可.从堆中取出的数据项是从大到小排列的.因为根节点永远是最大的,而堆中永远是取根节点.如果对堆这种数据结构不太了解的话,可以先看这篇博文:数据结构和算法之 堆,这里不再赘述. 下面我们来看看堆排序的实现(如果程序有不清楚的地方,也可以参考上面那篇博文). [java] view plain copy   public

堆排序(Heapsort)是利用堆这种数据结构的排序算法。堆是一个近似完全二叉树的结构。

堆的性质:即子结点的键值或索引总是小于(或者大于)它的父节点. 堆节点的访问 通常堆是通过一维数组来实现的.在起始数组为 0 的情形中: 堆的根节点(即堆积树的最大值)存放在数组位置 1 的地方; 注意:不使用位置 0,否则左子树永远为 0[2] 父节点i的左子节点在位置 (2*i); 父节点i的右子节点在位置 (2*i+1); 子节点i的父节点在位置 floor(i/2); 堆的操作 在堆的数据结构中,堆中的最大值总是位于根节点.堆中定义以下几种操作: 最大堆调整(Max_Heapify):将

理解二叉堆数据结构及Swift的堆排序算法实现示例_Swift

二叉堆的性质1.二叉堆是一颗完全二叉树,最后一层的叶子从左到右排列,其它的每一层都是满的 2.最小堆父结点小于等于其每一个子结点的键值,最大堆则相反 3.每个结点的左子树或者右子树都是一个二叉堆 下面是一个最小堆: 堆的存储通常堆是通过一维数组来实现的.在起始数组为 0 的情形中: 1.父节点i的左子节点在位置 (2*i+1); 2.父节点i的右子节点在位置 (2*i+2); 3.子节点i的父节点在位置 floor((i-1)/2); 维持堆的性质我们以最大堆来介绍(后续会分别给出最大堆和最小堆