第9章排序内部.ppt

  1. 1、本文档共76页,可阅读全部内容。
  2. 2、原创力文档(book118)网站文档一经付费(服务费),不意味着购买了该文档的版权,仅供个人/单位学习、研究之用,不得用于商业用途,未经授权,严禁复制、发行、汇编、翻译或者网络传播等,侵权必究。
  3. 3、本站所有内容均由合作方或网友上传,本站不对文档的完整性、权威性及其观点立场正确性做任何保证或承诺!文档内容仅供研究参考,付费前请自行鉴别。如您付费,意味着您自己接受本站规则且自行承担风险,本站不退款、不进行额外附加服务;查看《如何避免下载的几个坑》。如果您已付费下载过本站文档,您可以点击 这里二次下载
  4. 4、如文档侵犯商业秘密、侵犯著作权、侵犯人身权等,请点击“版权申诉”(推荐),也可以打举报电话:400-050-0827(电话支持时间:9:00-18:30)。
查看更多
具体做法: 把待排序的记录的关键字存放在数组r[1..n]之中,将r 看成是一棵完全二叉树的顺序表示,每个结点表示一个记录,第一个记录r[1]作为二叉树的根,以下各记录r[2...n]依次逐层从左到右顺序排列,任意结点r[i]的左孩子是r[2i],右孩子是r[2i+1],双亲是r[?i/2? ]。对这棵完全二叉树进行调整,使各结点的关键字值满足下列条件: r[i].key≥r[2i].key并且r[i].key≥r[2i+1].key(i=1,2, ... ?n/2? ),满足这个条件的完全二叉树为堆。 堆是满足下列性质的数列{r1, r2, …,rn}: 或 堆的定义: {12, 36, 27, 65, 40, 34, 98, 81, 73, 55, 49} 例如: 是小根堆 不是堆 (小根堆) (大根堆) ri r2i r2i+1 若将该数列视作完全二叉树, 则 r2i 是 ri 的左孩子; r2i+1 是 ri 的右孩子。 12 36 27 65 49 81 73 55 40 34 98 例如: 14 {12, 36, 27, 65, 40, 14, 98, 81, 73, 55, 49} 堆排序的过程主要需要解决两个问题:(1) 按堆定义建初堆(2)去掉最大元之后重建堆,得到次大元。 问题1:当堆顶元素改变时,如何重建堆? 首先将完全二叉树根结点中的记录移出,该记录称为待调整记录。此时根结点相当于空结点。从空结点的左、右子中选出一个关键字较小的记录,如果该记录的关键字小于待调整记录的关键字,则将该记录上移至空结点中。此时,原来那个关键字较小的子结点相当于空结点。重复上述移动过程,直到空结点左、右子的关键字均不小于待调整记录的关键字。此时,将待调整记录放入空结点即可。上述调整方法相当于把待调整记录逐步向下“筛”的过程,所以一般称为“筛选”法。 所谓“筛选”指的是,对一棵左/右子树均为堆的完全二叉树,“调整”根结点使整个二叉树也成为一个堆。 堆 堆 筛选 98 81 49 73 55 64 12 36 27 40 例如: 是大根堆 12 但在 98 和 12 进行互换之后,它就不是堆了, 因此,需要对它进行“筛选”。 98 12 81 73 64 12 98 比较 比较 筛选算法为: void sift(RecordType r[], int k,int m) /* 假设r[k..m]是以r[k]为根的完全二叉树,且分别以r[2k]和r[2k+1]为根的左、右子树为大根堆,调整r[k],使整个序列r[k..m]满足堆的性质 */ {t= r[k] ; /* 暂存“根”记录r[k] */ x=r[k].key ;i=k ;j=2*i ;finished=FALSE ; while( j=m ! finished ) { if (jm r[j].key r[j+1].key ) j=j+1; /* 若存在右子树,且右子树根的关键字大,则沿右分支“筛选” */ if ( x= r[j].key) finished=TRUE ; /* 筛选完毕 */ else { r[i] = r[j] ; i=j ; j=2*i ; } /* 继续筛选 */ } r[i] =t ; /* r[k]填入到恰当的位置 */ } /* sift */ 问题2:如何由一个任意序列建初堆? 一个任意序列看成是对应的完全二叉树,由于叶结点可以视为单元素的堆,因而可以反复利用“筛选”法,自底向上逐层把所有子树调整为堆,直到将整个完全二叉树调整为堆。 建堆算法如下: void crt_heap(RecordType r[], int length ) /*对记录数组r建堆,length为数组的长度*/ { n= length; for ( i=n/2 ; i= 1 ; --i) /* 自第个记录开始进行筛选建堆 */ sift(r,i,n) ;  } 问题3:如何利用堆进行排序? 进行堆排序的步骤:①将待排序记录按照堆的定义建初堆(算法9.10),并输出堆顶元素;②调整剩余的记录序列,利用筛选法将前n-i个元素重新筛选建成为一个新堆,再输出堆顶元素;③重复执行步骤②n-1次进行筛选, 新筛选成的堆会越来越小,而新堆后面的有序关键字会越来越多,最后使待排序记录序列成为一个有序的序列,这个过程称之为堆排序。 堆排序的算法为: void HeapSort(RecordType r[],int length) /* 对r[1..n]进行堆排序,执行本算法后,r中记录按关键字由大到小有序排列

文档评论(0)

精华文档888 + 关注
实名认证
内容提供者

该用户很懒,什么也没介绍

1亿VIP精品文档

相关文档