`
runfeel
  • 浏览: 907286 次
文章分类
社区版块
存档分类
最新评论

堆排序解析

 
阅读更多

一、堆的定义

是n个元素的序列H={k1, k2 , … kn},满足ki≤k2i当2i≤n时 ki≥k2i当2i≤n时或者

ki≤k2i+1 当2i+1≤n时
ki ≥k2i+1 当2i+1≤n时
由堆的定义知,堆是一棵以k1为根的完全二叉树。若对该二叉树的结点进行编号(从上到下,从左到右),得到的序列就是将二叉树的结点以顺序结构存放,堆的结构正好和该序列结构完全一致。
二、 堆的性质
① 堆是一棵采用顺序存储结构的完全二叉树, k1是根结点;
② 堆的根结点是关键字序列中的最小(或最大)值,分别称为小(或大)根堆;
③ 从根结点到每一叶子结点路径上的元素组成的序列都是按元素值(或关键字值)非递减(或非递增)的;
④堆中的任一子树也是堆。
利用堆顶记录的关键字值最小(或最大)的性质,从当前待排序的记录中依次选取关键字最小(或最大)的记录,就可以实现对数据记录的排序,这种排序方法称为堆排序。
三、 堆排序思想
① 对一组待排序的记录,按堆的定义建立堆;
② 将堆顶记录和最后一个记录交换位置,则前n-1个记录是无序的,而最后一个记录是有序的;
③ 堆顶记录被交换后,前n-1个记录不再是堆,需将前n-1个待排序记录重新组织成为一个堆,然后将堆顶记录和倒数第二个记录交换位置,即将整个序列中次小关键字值的记录调整(排除)出无序区;
④ 重复上述步骤,直到全部记录排好序为止。
结论:排序过程中,若采用小根堆,排序后得到的是非递减序列;若采用大根堆,排序后得到的是非递增序列。
堆排序的关键
① 如何由一个无序序列建成一个堆?
② 如何在输出堆顶元素之后,调整剩余元素,使之成为一个新的堆?
四、堆调整
输出堆顶元素之后,以堆中最后一个元素替代之;然后将根结点值与左、右子树的根结点值进行比较,并与其中小者进行交换;重复上述操作,直到是叶子结点或其关键字值小于等于左、右子树的关键字的值,将得到新的堆。称这个从堆顶至叶子的调整过程为“筛选
堆调整算法实现
void Heap_adjust(Sqlist *H, int s, int m)
/*  H->R[s…m]中记录关键字除H->R[s].key均满足堆定义  */
/*  调整H->R[s]的位置使之成为小根堆  */
{  int j=s, k=2*j ;     /*  计算H->R[j]的左孩子的位置  */
H->R[0]=H->R[j] ;       /*  临时保存H->R[j]  */ 
for (k=2*j; k<=m; k=2*k)
{  if ((k<m)&&(LT(H->R[k+1].key, H->R[k].key)) 
    k++ ;      /*  选择左、右孩子中关键字的最小者  */
if  ( LT(H->R[k].key, H->R[0].key) )
    {   H->R[j]=H->R[k] ; j=k ; k=2*j  }
else  break ;
}
H->R[j]=H->R[0] ; 
}

五、堆的建立
利用筛选算法,可以将任意无序的记录序列建成一个堆,设R[1],R[2], …,R[n]是待排序的记录序列。
将二叉树的每棵子树都筛选成为堆。只有根结点的树是堆。第⌊n/2⌋个结点之后的所有结点都没有子树,即以第ën/2û个结点之后的结点为根的子树都是堆。因此,以这些结点为左、右孩子的结点,其左、右子树都是堆,则进行一次筛选就可以成为堆。同理,只要将这些结点的直接父结点进行一次筛选就可以成为堆…。
只需从第ën/2û个记录到第1个记录依次进行筛选就可以建立堆。
可用下列语句实现:
for (j=n/2; j>=1; j--)
Heap_adjust(R, j , n) ;
六、堆排序实现
堆的根结点是关键字最小的记录,输出根结点后,是以序列的最后一个记录作为根结点,而原来堆的左、右子树都是堆,则进行一次筛选就可以成为堆。
void  Heap_Sort(Sqlist *H)
{  int j ;
for (j=H->length/2; j>0; j--)
Heap_adjust(H, j , H->length) ;   /*   初始建堆   */
for (j=H->length/2; j>=1; j--)
{  H->R[0]=H->R[1] ; H->R[1]=H->R[j] ;
H->R[j]=H->R[0] ;   /*   堆顶与最后一个交换   */
Heap_adjust(H, 1, j-1) ; 
}
}

七、算法分析
主要过程:初始建堆和重新调整成堆。设记录数为n,所对应的完全二叉树深度为h 。
◆ 初始建堆:每个非叶子结点都要从上到下做“筛选”。第i层结点数≤2i-1,结点下移的最大深度是h-i,而每下移一层要比较2次,则比较次数C1(n)为:
堆排序的比较次数的数量级为:T(n)=O(n㏒2n);而附加空间就是交换时所用的临时空间,故空间复杂度为:S(n)=O(1) 。


分享到:
评论

相关推荐

    简单选择排序及堆排序源代码

    这是我的博客 《漫谈经典排序算法:一、从简单选择排序到堆排序的深度解析》中涉及到的源代码,详细解析请关注本人博客 http://blog.csdn.net/Touch_2011

    [C++算法入门]-堆排序

    文档中包含了堆排序的基本原理和实现方法,并提供了详细的代码示例和解析。 通过学习和完成这个练习,读者将能够掌握堆排序算法的思想和实现过程,并了解其在排序算法中的应用。此外,文档还提供了练习题和答案,...

    java堆排序原理及算法实现

    本篇文章主要介绍了堆排序的简介,定义,算法实现以及堆排序的性质。想要了解的朋友可以参考下

    深入解析堆排序的算法思想及Java代码的实现演示

    堆排序基于二叉堆结构即完全二叉树,可利用最大堆和最小堆的组建方式来进行排序,这里就来深入解析堆排序的算法思想及Java代码的实现演示

    数据结构 排序 思考题2

    题目一:在堆排序中,元素下标从0开始。则对于下标为i的元素,其左、右孩子的下标分别为: A. 2i-1, 2i B. 2i, 2i+1 C. 2i+1, 2i+2 D. 2i+2, 2i+3 选C 0的左子1右子2,代进去,只有C对。 题目二:对N个记录进行堆...

    堆排序——Java与Go实现

    堆排序是使用堆这种数据结构进行排序的方法。(好像是废话) 思路分析 首先,我们将待排序的数组看作一个完全二叉树 将此二叉树转成大顶堆或者小顶堆 将堆顶元素与堆的最后一个元素互换,之后丢弃最后一个元素 重复...

    SAA:排序算法解析

    SAA-排序算法分析SAA是一个C程序,用于对以下算法的C实现进行基准测试: 气泡排序选择排序插入排序贝壳排序堆排序合并排序快速排序计数排序用法无需用户输入/配置,该程序将根据您的计算机规格,为每种排序算法实现...

    C语言实例解析精粹(第二版) 光盘代码

    047 堆排序 048 归并排序 049 基数排序 050 二叉搜索树操作 051 二项式系数递归 052 背包问题 053 顺序表插入和删除 054 链表操作(1) 055 链表操作(2) 056 单链表就地逆置 057 运动会分数统计 058 双链表 059 ...

    C++ 排序算法的学案与模板

    内容简介: 涵盖 - 插入排序 & - 冒泡排序 & - 选择排序 & - 希尔排序 & - 归并排序 & - 快速排序 & - 计数排序 & - 堆排序 模板与解析。 适合人群: 普及早期的萌新 OIer 们。

    十大排序算法.rar

    常见排列算法,十大排列算法,GIF解析,快速掌握数据结构的算法问题,非常适合初学者,入门级别。插入排序,堆排序,基数排序,快速排序,冒泡排序,希尔排序,选择排序

    java二分法排序源码-Article:十大经典排序算法动画,看我就够了!

    常见的内部排序算法有:插入排序、希尔排序、选择排序、冒泡排序、归并排序、快速排序、堆排序、基数排序等。 用一张图概括: 关于时间复杂度: 平方阶 (O(n2)) 排序 各类简单排序:直接插入、直接选择和冒泡排序。 ...

    二叉堆的概念及其应用.pptx

    二叉堆的概念及其应用,里面包含果子合并、堆排序、鱼塘钓鱼、最小函数值、Sequence等重要题型的详细解析

    c语言实例解析——数据结构篇(42-74)

    047 堆排序 048 归并排序 049 基数排序 050 二叉搜索树操作 051 二项式系数递归 052 背包问题 053 顺序表插入和删除 054 链表操作(1) 055 链表操作(2) 056 单链表就地逆置 057 运动会分数统计 058 双...

    python课堂笔记.zip

    目录 01概述及环境搭建 02基础语法(完整版) 02基础语法 Pyenv安装(可选择文字) Python环境安装 Windows安装Python3、IPython、Pycharm 练习参考 课堂练习 内置数据结构01list ...树的遍历和堆排序 ......

    C语言实例解析精粹

    047 堆排序 048 归并排序 049 基数排序 050 二叉搜索树操作 051 二项式系数递归 052 背包问题 053 顺序表插入和删除 054 链表操作(1) 055 链表操作(2) 056 单链表就地逆置 057 运动会分数统计 058 双...

    Algorithm:每天学习一个算法,克服一个难关!以下的源代码全是由JavaScript来实现的,而且每实现一个算法,我都将写博客对算法进行解析,我一直认为写博客能加深自己对知识点的理解。另外,欢迎大家访问我的博客网站

    20170307此目录下包含优先权的三种实现方式以及堆排序的源代码,你可以在看到我对优先所有权的解析,不过对于堆排序,可能是我实现的有问题,由于我一直对性能还尚不满意,所以还没有总结成博客,不过目前正在积极...

    数据结构与算法经典问题解析-Java语言描述

    本书强调问题及其分析,而非理论阐述,共分为21章,讲述了基本概念、递归和回溯、链表、栈、队列、树、优先队列和堆、并查集DAT、图算法、排序、查找、选择算法(中位数)、符号表、散列、字符串算法、算法设计技术...

    Java数据结构和算法

    (1)数据结构与算法概念...(15)排序算法(五)——快速排序 (16)排序算法(六)——希尔排序 (17)排序算法(七)——堆排序 (18)排序算法(八)——基数排序 (19)排序算法(九)——八大排序算法总结

    算法设计 - 排序、动态规划、数学问题 - 实用编程资源合集

    其中包含多种排序算法的实现与分析,如快速排序、归并排序、堆排序等,以及动态规划在解决最长公共子序列、矩阵链相乘问题上的应用。此外,还探讨了三壶谜题、交替放置的碟子等经典数学问题的算法思路。 适用人群为...

    算法/数据结构/Python/剑指offer/机器学习/leetcode

    算法/数据结构/Python/剑指offer/机器学习/leetcode 数据结构markdown格式 链表及常见操作 平衡查找树AVL 三种方法检测变位词Anagram ...解析树ParseTree ...堆排序 正则表达式和一个使用正则表达式的图片爬虫

Global site tag (gtag.js) - Google Analytics