数据结构课件-第九章.ppt
《数据结构课件-第九章.ppt》由会员分享,可在线阅读,更多相关《数据结构课件-第九章.ppt(60页珍藏版)》请在三一办公上搜索。
1、第九章 内部排序,9.1 排序的基本概念,9.2 插入类排序,9.3 交换类排序法,9.4 选择类排序法,9.5 归并排序,9.6 分配类排序,9.7 各种排序方法的综合比较,返回主目录,9.1 排序的基本概念,排序:有n个记录的序列R1,R2,Rn,其相应关键字的序列是K1,K2,Kn,相应的下标序列为1,2,n。通过排序,要求找出当前下标序列1,2,n的一种排列p1,p2,pn,使得相应关键字满足如下的非递减(或非递增)关系,即:Kp1 Kp2 Kpn,这样就得到一个按关键字有序的记录序列:Rp1,Rp2,Rpn。,返回主目录,内部排序:整个排序过程完全在内存中进行,称为内部排序。,外部排
2、序:由于待排序记录数据量太大,内存无法容纳全部数据,排序需要借助外部存储设备才能完成,称为外部排序。,稳定排序和不稳定排序:假设Ki=Kj(1in,1jn,ij),若在排序前的序列中Ri领先于Rj(即ij),经过排序后得到的序列中Ri仍领先于Rj,则称所用的排序方法是稳定的;反之,当相同关键字的领先关系在排序过程中发生变化者,则称所用的排序方法是不稳定的。,返回主目录,在排序过程中,一般进行两种基本操作:,(1)比较两个关键字的大小;(2)将记录从一个位置移动到另一个位置。,对于第二种操作,需要采用适当地存储方式,即向量结构、链表结构以及记录向量与地址向量结合的表示方法。,我们重点来讨论在向量
3、存储结构上各种排序方法的实现。,返回主目录,9.2 插入类排序,基本思想:在一个已排好序的记录子集的基础上,每一步将下一个待排序的记录有序插入到已排好序的记录子集中,直到将所有待排记录全部插入为止。,9.2.1 直接插入排序,基本操作是将第i个记录插入到前面i-1个已排好序的记录中,具体过程为:将第i个记录的关键字Ki顺次与其前面记录的关键字Ki-1,Ki-2,K1进行比较,将所有关键字大于Ki的记录依次向后移动一个位置,直到遇见一个关键字小于或者等于Ki的记录Kj,此时Kj后面必为空位置,将第i个记录插入空位置即可。,返回主目录,48 62 35 77 55 14 35 98 48 62 3
4、5 77 55 14 35 98 35 48 62 77 55 14 35 98 35 48 62 77 55 14 35 98 35 48 55 62 77 14 35 98 14 35 48 55 62 77 35 98 14 35 35 48 55 62 77 98 14 35 35 48 55 62 77 98,下面给出了一个完整的直接插入排序实例。图中大括号内为当前已排好序的记录子集合。,返回主目录,假设待排序记录存放在r1.n之中,为了提高效率,我们附设一个监视哨r0,使得r0始终存放待插入的记录。,void InsSort(RecordType r,int length)/*对记
5、录数组r做直接插入排序,length为数组的长度*/for(i=2;i length;i+)r0=ri;j=i-1;/*将待插入记录存放到r0中*/while(r0.key rj.key)/*寻找插入位置*/rj+1=rj;j=j-1;rj+1=r0;/*将待插入记录插入到已排序的序列中*/*InsSort*/,直接插入排序算法,返回主目录,该算法的要点是:使用监视哨r0临时保存待插入的记录。从后往前查找应插入的位置。查找与移动用同一循环完成。,直接插入排序算法分析:,从空间角度来看,它只需要一个辅助空间r0。从时间耗费角度来看,主要时间耗费在关键字比较和移动元素上。,直接插入排序方法是稳定的
6、排序方法。,返回主目录,9.2.2 折半插入排序,void BinSort(RecordType r,int length)/*对记录数组r进行折半插入排序,length为数组的长度*/for(i=2;i=low;-j)rj+1=rj;/*记录依次向后移动*/rlow=x;/*插入记录*/,返回主目录,采用折半插入排序法,可减少关键字的比较次数。每插入一个元素,需要比较的次数最大为折半判定树的深度,如插入第i个元素时,设i=2j,则需进行log2i次比较,因此插入n-1个元素的平均关键字的比较次数为O(nlog2n)。虽然折半插入排序法与直接插入排序法相比较,改善了算法中比较次数的数量级,但其
7、并未改变移动元素的时间耗费,所以折半插入排序的总的时间复杂度仍然是O(n2)。,算法分析:,返回主目录,9.2.3 表插入排序,表插入排序是采用链表存储结构进行插入排序的方法。表插入排序的基本思想是:先在待插入记录之前的有序子链表中查找应插入位置,然后将待插入记录插入链表。,typedef int KeyType;typedef struct KeyType key;OtherType other_data;int next;RecordType1;,类型说明如下:,返回主目录,void SLinkListSort(RecordType1 r,int length)int n=length;r
8、0.next=n;rn.next=0;for(i=n-1;i=1;-i)p=r0.next;q=0;while(p0/*修改指针,完成插入*/*SLinkListSort*/,表插入排序算法,返回主目录,算法分析:,每插入一条记录,最大的比较次数等于已排好序的记录个数,即当前循环链表长度。总的比较次数为:,因此表插入排序的时间复杂度为T(n)=O(n2)。,返回主目录,9.4 选择类排序法,选择排序的基本思想是:每一趟在n-i+1(i=1,2,n-1)个记录中选取关键字最小的记录作为有序序列中第i个记录。,9.4.1 简单选择排序,基本思想:第i趟简单选择排序是指通过n-i次关键字的比较,从n
9、-i+1个记录中选出关键字最小的记录,并和第i个记录进行交换。共需进行i-1趟比较,直到所有记录排序完成为止。,选择排序示例见P240的图9.5所示。,返回主目录,简单选择排序的算法描述如下:,void SelectSort(RecordType r,int length)/*对记录数组r做简单选择排序,length为数组的长度*/n=length;for(i=1;i=n;+i)k=i;for(j=i+1;j=n;+j)if(rj.key rk.key)k=j;if(k!=i)x=ri;ri=rk;rk=x;/*SelectSort*/,返回主目录,简单选择排序算法分析:,在简单选择排序过程中
10、,所需移动记录的次数比较少。最好情况下,即待排序记录初始状态就已经是正序排列了,则不需要移动记录。最坏情况下,即待排序记录初始状态是按逆序排列的,则需要移动记录的次数最多为3(n-1)。进行比较操作的时间复杂度为O(n2)。,返回主目录,9.4.2 树型选择排序,树型选择排序也称作锦标赛排序。它的基本思想是:先把待排序的n个记录的关键字两两进行比较,取出较小者。然后再在 n/2 个较小者中,采用同样的方法进行比较选出每两个中的较小者,如此反复,直至选出最小关键字记录为止。,例如p241的图9.6所示的树型选择排序,返回主目录,在树型选择排序中,被选中的关键字都是走了一条由叶子结点到根结点的比较
11、的过程,由于含有n个叶子节点的完全二叉数的深度为log2n+1,则在树型选择排序中,每选择一个小关键字需要进行log2n次比较,因此其时间复杂度为O(nlog2n)。移动记录次数不超过比较次数,故总的算法时间复杂度为O(nlog2n)。,算法分析:,返回主目录,9.4.3 堆排序,堆排序是对树型选择排序的进一步改进。采用堆排序时,只需要一个记录大小的辅助空间。堆排序是在排序过程中,将向量中存储的数据看成一棵完全二叉树,利用完全二叉树中双亲结点和孩子结点之间的内在关系来选择关键字最小的记录,即待排序记录仍采用向量数组方式存储,并非采用树的存储结构,而仅仅是采用完全二叉树的顺序结构的特征进行分析而
12、已。,返回主目录,具体做法:,把待排序的记录的关键字存放在数组r1.n之中,将r 看成是一棵完全二叉树的顺序表示,每个结点表示一个记录,第一个记录r1作为二叉树的根,以下各记录r2.n依次逐层从左到右顺序排列,任意结点ri的左孩子是r2i,右孩子是r2i+1,双亲是ri/2。对这棵完全二叉树进行调整,使各结点的关键字值满足下列条件:ri.keyr2i.key并且ri.keyr2i+1.key(i=1,2,.n/2),满足这个条件的完全二叉树为堆。,返回主目录,堆中根结点的关键字最大,称为大根堆。反之,如果这棵完全二叉树中任意结点的关键字大于或者等于其左孩子和右孩子的关键字(当有左孩子或右孩子时
13、),对应的堆为小根堆。,一个大根堆和一个小根堆的示例见p242的图9.7所示。,返回主目录,堆排序堆的定义:n个元素的序列(k1,k2,kn),当且仅当满足下列关系时,称之为堆,例(96,83,27,38,11,9),例(13,38,27,50,76,65,49,97),可将堆序列看成完全二叉树,则堆顶元素(完全二叉树的根)必为序列中n个元素的最小值或最大值,堆排序的过程主要需要解决两个问题:(1)按堆定义建初堆(2)去掉最大元之后重建堆,得到次大元。,问题1:当堆顶元素改变时,如何重建堆?,首先将完全二叉树根结点中的记录移出,该记录称为待调整记录。此时根结点相当于空结点。从空结点的左、右子中
14、选出一个关键字较小的记录,如果该记录的关键字小于待调整记录的关键字,则将该记录上移至空结点中。此时,原来那个关键字较小的子结点相当于空结点。重复上述移动过程,直到空结点左、右子的关键字均不小于待调整记录的关键字。此时,将待调整记录放入空结点即可。上述调整方法相当于把待调整记录逐步向下“筛”的过程,所以一般称为“筛选”法。,返回主目录,例,筛选过程示例见p316的图9.8所示。,筛选算法为:,void sift(RecordType r,int,int)/*假设k.m是以k为根的完全二叉树,且分别以2k和2k+1为根的左、右子树为大根堆,调整rk,使整个序列rk.m满足堆的性质*/t=rk;/*
15、暂存“根”记录rk*/x=rk.key;i=k;j=2*i;finished=FALSE;while(j=m&!finished)if(jm&rj.key rj+1.key)j=j+1;/*若存在右子树,且右子树根的关键字大,则沿右分支“筛选”*/,返回主目录,if(x=rj.key)finished=TRUE;/*筛选完毕*/else ri=rj;i=j;j=2*i;/*继续筛选*/ri=t;/*rk填入到恰当的位置*/*sift*/,返回主目录,问题2:如何由一个任意序列建初堆?,一个任意序列看成是对应的完全二叉树,由于叶结点可以视为单元素的堆,因而可以反复利用“筛选”法,自底向上逐层把所
16、有子树调整为堆,直到将整个完全二叉树调整为堆。,建堆算法如下:,void crt_heap(RecordType r,int length)/*对记录数组r建堆,length为数组的长度*/n=length;for(i=n/2;i=1;-i)/*自第个记录开始进行筛选建堆*/sift(r,i,n);,返回主目录,例如,已知关键字序列:48,62,35,77,55,14,35,98,要求将其筛选为一个堆。在此,n=8,所以应从第个结点77开始筛选。从无序序列的第n/2个元素,即此无序序列对应的完全二叉树的最后一个非终端结点)起,至第一个元素止.建堆过程见P317的图9.9。图中箭头所指为当前待筛
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 数据结构 课件 第九
![提示](https://www.31ppt.com/images/bang_tan.gif)
链接地址:https://www.31ppt.com/p-5986082.html