数据结构-严蔚敏10_第1页
数据结构-严蔚敏10_第2页
数据结构-严蔚敏10_第3页
数据结构-严蔚敏10_第4页
数据结构-严蔚敏10_第5页
已阅读5页,还剩72页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1、1210.1 概述概述10.2 插入排序插入排序10.3 快速排序快速排序10.4 堆排序堆排序10.5 归并排序归并排序10.6 基数排序基数排序10.6 各种排序方法的综合比较各种排序方法的综合比较10.8 外部排序外部排序310.1 概概 述述一、排序的定义一、排序的定义二、内部排序和外部排序二、内部排序和外部排序三、内部排序方法的分类三、内部排序方法的分类4一、什么是排序?一、什么是排序?排序是计算机内经常进行的一种操作,其目的是将一组“无序无序”的记录序列调的记录序列调整为整为“有序有序”的记录序列。例如:将下列关键字序列52, 49, 80, 36, 14, 58, 61, 23,

2、 97, 75调整为14, 23, 36, 49, 52, 58, 61 ,75, 80, 975 一般情况下,假设含n个记录的序列为 R1, R2, , Rn 其相应的关键字序列为 K1, K2, ,Kn 这些关键字相互之间可以进行比较,即在它们之间存在着这样一个关系 Kp1Kp2Kpn按此固有关系将上式记录序列重新排列为 Rp1, Rp2, ,Rpn 的操作操作称作排序排序。6二、内部排序和外部排序二、内部排序和外部排序若整个排序过程不需要访问外存不需要访问外存便能完成,则称此类排序问题为内部排内部排序序; 反之,若参加排序的记录数量很大, 整个序列的排序过程不可能在内存中 完成,则称此类

3、排序问题为外部排序外部排序。7三、内部排序的方法三、内部排序的方法内部排序的过程是一个逐步扩大逐步扩大记录的有序序列长度有序序列长度的过程。经过一趟排序经过一趟排序有序序列区无 序 序 列 区有序序列区无 序 序 列 区8基于不同的“扩大扩大” 有序序列长度的方法,内部排序方法方法,内部排序方法大致可分下列几种类型:插入类插入类交换类交换类选择类选择类 归并类归并类其它方法其它方法9待排记录的数据类型定义如下待排记录的数据类型定义如下:const MAXSIZE = 1000; / 待排顺序表最大长度待排顺序表最大长度typedef int KeyType; / 关键字类型为整数类型关键字类型

4、为整数类型typedef struct KeyType key; / 关键字项关键字项 InfoType otherinfo; / 其它数据项其它数据项 RcdType; / 记录类型记录类型typedef struct RcdType rMAXSIZE+1; / r0闲置闲置 int length; / 顺序表长度顺序表长度 SqList; / 顺序表类型顺序表类型10 10. 2 插插 入入 排排 序序11有序序列R1.i-1Ri无序序列 Ri.n一趟直接插入排序的基本思想:有序序列R1.i无序序列 Ri+1.n12实现实现“一趟插入排序一趟插入排序”可分三步进行:可分三步进行:3将Ri

5、插入插入(复制)到Rj+1的位置上。2将Rj+1.i-1中的所有记录记录均后移后移 一个位置;1在R1.i-1中查找查找Ri的插入位置 j ; R1.j.key Ri.key Rj+1.i-1.key13直接插入排序直接插入排序(基于顺序查找)(基于顺序查找)表插入排序表插入排序(基于链表存储)(基于链表存储)不同的具体实现方法导致不同的算法描述不同的具体实现方法导致不同的算法描述折半插入排序折半插入排序(基于折半查找)(基于折半查找)希尔排序希尔排序(基于逐趟缩小增量)(基于逐趟缩小增量)14一、直接插入排序一、直接插入排序利用 “顺序查找顺序查找”实现“在R1.i-1中查找查找Ri的插入位

6、置”算法的实现要点:算法的实现要点:15从Ri-1起向前进行顺序查找, 监视哨设置在R0;R0 = Ri; / 设置“哨兵”循环结束表明Ri的插入位置为 j +1R0jRifor (j=i-1; R0.keyRj.key; -j); / 从后往前找j=i-1插入位置插入位置16 对于在查找过程中找到的那些关键字不小于Ri.key的记录,并在查找的同时实现记录向后移动;for (j=i-1; R0.keyRj.key; -j); Rj+1 = RjR0jRij= i-1上述循环结束后可以直接进行“插入”插入位置插入位置17令 i = 2,3,, n, 实现整个序列的排序。for ( i=2; i

7、=n; +i ) if (Ri.keyRi-1.key) 在 R1.i-1中查找Ri的插入位置; 插入Ri ; 18void InsertionSort ( SqList &L ) / 对顺序表 L 作直接插入排序。 for ( i=2; i=L.length; +i ) if (L.ri.key L.ri-1.key) /if / InsertSortL.r0 = L.ri; / 复制为监视哨复制为监视哨L.ri = L.ri-1;for ( j=i-2; L.r0.key L.rj.key; - j ) L.rj+1 = L.rj; / 记录后移记录后移L.rj+1 = L.r0;

8、 / 插入到正确位置插入到正确位置19内部排序的时间分析时间分析:实现内部排序的基本操作基本操作有两个:(2)“移动移动”记录。(1)“比较比较”序列中两个关键字的 大小;20对于直接插入排序:最好的情况(关键字在记录序列中顺序有序):最好的情况(关键字在记录序列中顺序有序):“比较”的次数:最坏的情况(关键字在记录序列中逆序有序):最坏的情况(关键字在记录序列中逆序有序):“比较”的次数:112nni02) 1)(4() 1(2nnini“移动”的次数:“移动”的次数:2)1(2nnini( )221 因为 R1.i-1 是一个按关键字有序的有序序列,则可以利用折半查找折半查找实现“在R1.

9、i-1中查找查找Ri的插入位置”,如此实现的插入排序为折半插折半插入入排序。二、折半插入排序二、折半插入排序22void BiInsertionSort ( SqList &L ) / BInsertSort在在 L.r1.i-1中折半查找插入位置;中折半查找插入位置;for ( i=2; i=high+1; -j ) L.rj+1 = L.rj; / 记录后移L.rhigh+1 = L.r0; / 插入23low = 1; high = i-1;while (low=high) m = (low+high)/2; / 折半if (L.r0.key L.rm.key) high = m

10、-1; / 插入点在低半区else low = m+1; / 插入点在高半区24ilowhighmmlowlowmhighilowhighmhighmhighmlow例如:再如:插入位置插入位置14 36 49 52 80 58 61 23 97 75L.r14 36 49 52 58 61 80 23 97 75L.r25 四、希尔排序(又称缩小增量排序)四、希尔排序(又称缩小增量排序) 基本思想:对待排记录序列先作“宏观”调整,再作“微观”调整。 所谓“宏观”调整,指的是,“跳跃式”的插入排序。 具体做法为:26将记录序列分成若干子序列,分别对每个子序列进行插入排序。其中,d 称为增量,它

11、的值在排序过程中从大到小逐渐缩小,直至最后一趟排序减为 1。例如:将 n 个记录分成 d 个子序列: R1,R1+d,R1+2d,R1+kd R2,R2+d,R2+2d,R2+kd Rd,R2d,R3d,Rkd,R(k+1)d 27例如:16 25 12 30 47 11 23 36 9 18 31 第一趟希尔排序,设增量 d =511 23 12 9 18 16 25 36 30 47 31 第二趟希尔排序,设增量 d = 39 18 12 11 23 16 25 31 30 47 36第三趟希尔排序,设增量 d = 1 9 11 12 16 18 23 25 30 31 36 47 28v

12、oid ShellInsert ( SqList &L, int dk ) for ( i=dk+1; i=n; +i ) if ( L.ri.key0&(L.r0.keyL.rj.key); j-=dk) L.rj+dk = L.rj; / 记录后移,查找插入位置 L.rj+dk = L.r0; / 插入 / if / ShellInsert29void ShellSort (SqList &L, int dlta, int t) / 增量为dlta的希尔排序 for (k=0; k1) / while / BubbleSorti = n;i = lastExchan

13、geIndex; / 本趟进行过交换的 / 最后一个记录的位置 if (Rj+1.key Rj.key) Swap(Rj, Rj+1); /iffor (j = 1; j i; j+)lastExchangeIndex = 1;lastExchangeIndex = j; /记下进行交换的记录位置33注意注意: :2. 一般情况下,每经过一趟“起泡”,“i 减一”,但并不是每趟都如此。例如例如:523197825531579 89i=7i=6for (j = 1; j i; j+) if (Rj+1.key Rj.key) 131. 起泡排序的结束条件为, 最后一趟没有进行最后一趟没有进行“交

14、换记录交换记录”。jjjjjji=2jj34时间分析时间分析: :最好的情况(关键字在记录序列中顺序有序):最好的情况(关键字在记录序列中顺序有序): 只需进行一趟起泡只需进行一趟起泡“比较比较”的次数:的次数:最坏的情况(关键字在记录序列中逆序有序):最坏的情况(关键字在记录序列中逆序有序): 需进行需进行n-1趟起泡趟起泡“比较比较”的次数:的次数:0“移动移动”的次数:的次数:“移动移动”的次数:的次数:n-12) 1() 1(2nnini2) 1(3) 1(32nnini35二、一趟快速排序(一次划分)二、一趟快速排序(一次划分)目标:目标:找一个记录,以它的关键字作为“枢轴枢轴”,凡

15、其关键字小于枢轴关键字小于枢轴的记录均移动至该记录之前移动至该记录之前,反之,凡关键字大于关键字大于枢轴枢轴的记录均移动至该记录之后移动至该记录之后。致使一趟排序一趟排序之后,记录的无序序列Rs.t将分割成两部分分割成两部分:Rs.i-1和Ri+1.t, 且 Rj.key Ri.key Rj.key (sji-1) 枢轴枢轴 (i+1jt)3652 49 80 36 14 58 61 97 23 75stlowhigh设设 Rs=52 为枢轴暂存在为枢轴暂存在R0的位置上的位置上 将 Rhigh.key 和 枢轴的关键字进行比较,要求Rhigh.key 枢轴的关键字 将 Rlow.key 和

16、枢轴的关键字进行比较,要求Rlow.key 枢轴的关键字high23low80high14low52例如例如R052lowhighhighhighlow37 可见,经过“一次划分一次划分” ,将关键字序列 52, 49, 80, 36, 14, 58, 61, 97, 23, 75 调整为: 23, 49, 14, 36, (52) 58, 61, 97, 80, 75 在调整过程中,设立了两个指针: low 和high 之后逐渐减小 high,增加 low,并保证 Rhigh.key52,和 Rlow.key52,否则进行记录的“交换”。38int Partition (Elem R, in

17、t low, int high) pivotkey = Rlow.key; while (lowhigh) while (low=pivotkey) -high; RlowRhigh; while (lowhigh & Rlow.key=pivotkey) +low; RlowRhigh; return low; / 返回枢轴所在位置 / Partition39int Partition (Elem R ,int low, int high) / Partition R0 = Rlow; pivotkey = Rlow.key; / 枢轴 while (lowhigh) while(l

18、ow=pivotkey) - high; / 从右向左搜索Rlow = Rhigh;while (lowhigh & Rlow.key=pivotkey) + low; / 从左向右搜索Rhigh = Rlow;Rlow = R0; return low;40三、快速排序三、快速排序 首先对无序的记录序列进行“一次划分一次划分”,之后分别分别对分割所得两个子序列“递归递归”进行快速排序进行快速排序。无 序 的 记 录 序 列无序记录子序列(1)无序子序列(2)枢轴枢轴一次划分分别进行快速排序41void QSort (SqList &L, int low, int high )

19、 / 对记录序列L.rlow.high进行快速排序 if (low high-1) / 长度大于1 / QSortpivotloc = Partition(L, low, high); / 对 L.rlow.high 进行一次划分一次划分QSort(L, low, pivotloc-1); / 对低子序列递归排序,pivotloc是枢轴位置是枢轴位置QSort(L, pivotloc+1, high); / 对高子序列递归排序42void QuickSort( SqList & L) / 对顺序表进行快速排序 QSort(L, 1, L.length); / QuickSort 第一次

20、调用函数 Qsort 时,待排序记录序列的上、下界分别为 1 和 L.length。43四、快速排序的时间分析四、快速排序的时间分析假设一次划分所得枢轴位置 i=k,则对n 个记录进行快排所需时间其中 Tpass(n)为对 n 个记录进行一次划分所需时间, 若待排序列中记录的关键字是随机分布的,则 k 取 1 至 n 中任意一值的可能性相同。T(n) = Tpass(n) + T(k-1) + T(n-k)44nkavgavgavgknTkTnCnnT1)() 1(1)(设 Tavg(1)b则可得结果:) 1ln() 1)(22()(nncbnTavg结论结论: 快速排序的时间复杂度为快速排序

21、的时间复杂度为O(nlogn)由此可得快速排序所需时间的平均值为:45 若待排记录的初始状态为按关键字有序若待排记录的初始状态为按关键字有序时,快速排序将蜕化为起泡排序时,快速排序将蜕化为起泡排序,其时间复杂度为O(n2)。 为避免出现这种情况,需在进行一次划分之前,进行“予处理予处理”,即: 先对 R(s).key, R(t).key 和 R(s+t)/2.key,进行相互比较,然后取取关键字为 “三者之三者之中中”的记录为枢轴为枢轴记录。4610.4 堆堆 排排 序序简简 单单 选选 择择 排排 序序堆堆 排排 序序47一、简单选择排序一、简单选择排序假设排序过程中,待排记录序列的状态为:

22、有序序列R1.i-1无序序列 Ri.n 第 i 趟简单选择排序从中选出关键字最小的记录有序序列R1.i无序序列 Ri+1.n48简单选择排序的算法描述如下:void SelectSort (Elem R, int n ) / 对记录序列R1.n作简单选择排序。 for (i=1; i0; -i ) HeapAdjust ( R, i, n ); / 建大顶堆for ( i=n; i1; -i ) R1Ri; / 将堆顶记录和当前未经排序子序列 / R1.i中最后一个记录相互交换 HeapAdjust(R, 1, i-1); / 对 R1 进行筛选54如何如何“建堆建堆”?两个问题两个问题:如何

23、如何“筛选筛选”?定义堆类型为定义堆类型为:typedef SqList HeapType; / 堆采用顺序表表示之55所谓“筛选筛选”指的是,对一棵左/右子树均为堆的完全二叉树,“调整调整”根结根结点点使整个二叉树也成为一个堆。堆堆筛选筛选5698814973556412362740例如例如:是大顶堆是大顶堆12但在 98 和 12 进行互换之后,它就不不是堆了因此,需要对它进行“筛选”98128173641298比较比较比较57void HeapAdjust (Elem &R, int s, int m) / 已知 Rs.m中记录的关键字除 Rs 之外均 / 满足堆的特征,本函数自

24、上而下调整 Rs 的 / 关键字,使 Rs.m 也成为一个大顶堆。 / HeapAdjustrc = Rs; / 暂存 Rs for ( j=2*s; j= Rj.key ) break; / 再作“根”和“子树根”之间的比较, / 若“=”成立,则说明已找到 rc 的插 / 入位置 s ,不需要继续往下调整Rs = Rj; s = j; / 否则记录上移,尚需继续往下调整if ( jm & Rj.keyRj+1.key ) +j; / 左/右“子树根”之间先进行相互比较 / 令 j 指示关键字较大记录的位置59建堆是一个从下往上进行建堆是一个从下往上进行“筛选筛选”的过程。的过程。4

25、0554973816436122798例如例如: 排序之前的关键字序列为123681734998817355 现在,左/右子树都已经调整为堆,最后只要调整根结点,使整个二叉树是个“堆”即可。9849406436122760堆排序的时间复杂度分析:堆排序的时间复杂度分析:1. 对深度为 k 的堆,“筛选”所需进行的关键字比较的次数至多为2(k-1);2. 对 n 个关键字,建成深度为 h (=log2n+1) 的堆,所需进行的关键字比较的次数至多 4n;3. 调整“堆顶” n-1 次,总共进行的关键 字比较的次数不超过 2 ( log2(n-1) + log2(n-2) + +log22) 2n

26、( log2n ) 因此,堆排序的时间复杂度为O(nlogn)6110.5 归归 并并 排排 序序归并排序的过程基于下列基本思想基本思想进行: 将两个或两个以上的有序子序列 “归并” 为一个有序序列。62在内部排序中,通常采用的是2-路归并排序。即:将两个位置相邻位置相邻的记录有序子序列归并为一个一个记录的有序序列。有有 序序 序序 列列 Rl.n有序子序列有序子序列 Rl.m有序子序列有序子序列 Rm+1.n这个操作对顺序表而言,是轻而易举的。63void Merge (Elem SR, Elem TR, int i, int m, int n) / 将有序的记录序列 SRi.m 和 SRm

27、+1.n / 归并为有序的记录序列 TRi.n / Mergefor (j=m+1, k=i; i=m & j=n; +k) / 将SR中记录由小到大地并入TR if (SRi.key=SRj.key) TRk = SRi+; else TRk = SRj+; 64if (i=m) TRk.n = SRi.m; / 将剩余的 SRi.m 复制到 TRif (j=n) TRk.n = SRj.n; / 将剩余的 SRj.n 复制到 TR65归并排序的算法归并排序的算法如果记录无序序列 Rs.t 的两部分 Rs. (s+t)/2 和 R (s+t)/2 +1.t分别按关键字有序,则利用上述

28、归并算法很容易将它们归并成整个记录序列是一个有序序列。 由此,应该先分别对这两部分进行 2-路归并排序。66例如:例如:52, 23, 80, 36, 68, 14 (s=1, t=6) 52, 23, 80 36, 68, 14 52, 23 80 52 23, 52 23, 52, 8036, 68 143636, 6814, 36, 68 14, 23, 36, 52, 68, 80 23 52 23 36 68 80146867void Msort ( Elem SR, Elem &TR1, int s, int t ) / 将SRs.t 归并排序为 TR1s.t if (s= =t) TR1s=SRs; else / Msort 68m = (s+t)/2; / 将SRs.t平分为SRs.m和SRm+1.tMsort (SR, TR2, s, m); / 递归地将SRs.m归并为有序的TR2s.mMsort (SR, TR2, m+1, t); /递归地SRm+1.t归并为有序的TR2m+1.tMerge (TR2, TR1, s, m, t); / 将TR2s.m和TR2m+1.t归并到TR1s.t69void MergeSort (SqList &L) / 对顺序表 L 作2-路归并排序。 MSort(R, R, 1, n); / Merge

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论