第10章 内部排序
第十章内部排序
10.2 插入排序
1、直接插入排序:续 •实现算法
Status InsertSort ( SqList &L ) { for ( i = 2; i <= L.length ; ++i ) if ( LT( L.r[i].key, L.r[i-1].key ) ) { L.r[0].key = L.r[i].key; //复制为哨兵 for ( j=i-1; LT( L.r[0].key, L.r[j].key ) ; - -j ) L.r[j+1] = L.r[j]; //后移记录 L.r[j+1] = L.r[0]; } } //InsertSort
1 物料管理
第十章 内部排序
学习内容
10.1 概述 10.2 插入排序 10.3 快速排序 10.4 选择排序 10.5 归并排序
SORT
2 物料管理
第十章 内部排序
10.1 概述
•定义
设有记录序列:{ R1、R2 ……….. Rn } 其相应的关键字序列为: { K1、K2 ……….. Kn }; 若存在一种确定的关系: Kx <= Ky <= … <= Kz,则将记录序列 { R1、R2 ……….. Rn } 排成按 该关键字有序的序列:{ Rx、Ry ……….. Rz } 的操作,称之为排序。
•性能分析 减少了查找比较次数,但并未降低时间复杂度,仍为O(n2)。 7
SORT
8 物料管理
第十章 内部排序
10.2 插入排序
3、 希尔(shell) 排序 •基本思想 先将整个待排记录序列分割成为若干个子序列分别进行直接插入排序,待整个序列 中的记录基本有序时,再对全体记录进行一次直接插入排序。
第十章_排序方法(数据结构ppt-严蔚敏)
第二个问题解决方法——筛选
方法:输出堆顶元素之后,以堆中最后一个元素替代之;然 后将根结点值与左、右子树的根结点值进行比较,并与其中 小者进行交换;重复上述操作,直至叶子结点,将得到新的 堆,称这个从堆顶至叶子的调整过程为“筛选”
例 38 50 97 76
13 27 65 49 13 38
97 27 38 50 76
2 (n 4)(n 1) 记录移动次数: (i 1) 2 i 2
i 2 n
若待排序记录是随机的,取平均值 n2 关键字比较次数: T(n)=O(n² ) 4 记录移动次数:
空间复杂度:S(n)=O(1)
n2 4
折半插入排序
排序过程:用折半查找方法确定插入位置的排序叫~
初始时令i=s,j=t 首先从j所指位置向前搜索第一个关键字小于x的记录,并和rp 交换 再从i所指位置起向后搜索,找到第一个关键字大于x的记录, 和rp交换 重复上述两步,直至i==j为止 再分别对两个子序列进行快速排序,直到每个子序列只含有 一个记录为止
x 例 初始关键字: 27 49 i 完成一趟排序: ( 27 38 13 49 65 i 13) 49 97 76 j 97 49 13 j 97 65 49 27 50 j 50)
13 38
76 65 27 49
堆排序:将无序序列建成一个堆,得到关键字最小 (或最大)的记录;输出堆顶的最小(大)值后,使 剩余的n-1个元素重又建成一个堆,则可得到n个元素 的次小值;重复执行,得到一个有序序列,这个过程 叫~ 堆排序需解决的两个问题:
如何由一个无序序列建成一个堆? 如何在输出堆顶元素之后,调整剩余元素,使之成为一个新 的堆?
按排序所需工作量
第十章排序答案
第10章排序一、选择题1.某内排序方法的稳定性是指( D )。
【南京理工大学 1997 一、10(2分)】A.该排序算法不允许有相同的关键字记录 B.该排序算法允许有相同的关键字记录C.平均时间为0(n log n)的排序方法 D.以上都不对2.下面给出的四种排序法中( D )排序法是不稳定性排序法。
【北京航空航天大学 1999 一、10 (2分)】 A. 插入 B. 冒泡 C. 二路归并 D. 堆积3.下列排序算法中,其中(D )是稳定的。
【福州大学 1998 一、3 (2分)】A. 堆排序,冒泡排序B. 快速排序,堆排序C. 直接选择排序,归并排序D. 归并排序,冒泡排序4.稳定的排序方法是( B )【北方交通大学 2000 二、3(2分)】A.直接插入排序和快速排序 B.折半插入排序和起泡排序C.简单选择排序和四路归并排序 D.树形选择排序和shell排序5.下列排序方法中,哪一个是稳定的排序方法?( B )【北方交通大学 2001 一、8(2分)】A.直接选择排序 B.二分法插入排序 C.希尔排序 D.快速排序6. 快速排序方法在( D )情况下最不利于发挥其长处。
【燕山大学 2001 一、3 (2分)】A. 要排序的数据量太大B. 要排序的数据中含有多个相同值C. 要排序的数据个数为奇数D. 要排序的数据已基本有序7. 以下序列不是堆的是( D )。
【西安电子科技大学 2001应用一、5 (2分)】A. (100,85,98,77,80,60,82,40,20,10,66)B. (100,98,85,82,80,77,66,60,40,20,10)C. (10,20,40,60,66,77,80,82,85,98,100)D. (100,85,40,77,80,60,66,98,82,10,20)8.下列四个序列中,哪一个是堆( C )。
【北京工商大学 2001 一、8 (3分)】A. 75,65,30,15,25,45,20,10B. 75,65,45,10,30,25,20,15C. 75,45,65,30,15,25,20,10D. 75,45,65,10,25,30,20,159.从未排序序列中依次取出一个元素与已排序序列中的元素依次进行比较,然后将其放在已排序序列的合适位置,该排序方法称为( A )排序法。
第10章-内部排序PPT课件
-
算法效率
时间复杂度
待排序记录按关键字从小到大排列(正序)
n
比较次数: 1 n 1 i2
移动次数: 0
待排序记录按关键字从大到小排列(逆序)
比较次数:
n i (n2)(n1)
i2
2
移动次数:
n
(n4)(n1)
(i1)
i2
2
待排序记录随机,取平均值
比较次数: n 2
4
移动次数: n 2
4
总的时间复杂度:T(n)=O(n2)
空间复杂度:S(n)=O(1)
-
3. 折半插入排序
排序过程:用折半查找方法确定插入位置。 举例:
i=1: (38) (49) 38 65 97 76 13 27 49
5 R’={5}
R={10,2}
2 R’={2,5}
R={2}
10 R’={2,5,10}
R={ }
2 R’={2,2,5,10}
-
2. 直接插入排序
排序过程:整个排序过程为n-1趟插入
将序列中第1个记录看成是一个有序子序列 从第2个记录开始,逐个进行插入,直至整个序列有序
R1 R2 …… Rn
内部排序适用于记录个数不很多的小文件; 外部排序则适用于记录个数太多,不能一次 将其全部放入内存的大文件
排序依据策略
插入排序:直接插入排序, 折半插入排序, 希尔排序 交换排序:冒泡排序, 快速排序 选择排序:简单选择排序, 堆排序 归并排序:2-路归并排序 基数排序
第十章内排习题
第十章内部排序一,选择1. 基于比较方法的n个数据的内部排序。
最坏情况下的时间复杂度能达到的最好下界是()。
A. O(nlogn)B. O(logn)C. O(n)D. O(n*n)2.下列排序算法中,其中()是稳定的。
A. 堆排序,冒泡排序B. 快速排序,堆排序C. 直接选择排序,归并排序D. 归并排序,冒泡排序3.若要求排序是稳定的,且关键字为实数,则在下列排序方法中应选()排序为宜。
A.直接插入 B.直接选择 C.堆 D.快速4.若需在O(nlog2n)的时间内完成对数组的排序,且要求排序是稳定的,则可选择的排序方法是()。
A. 快速排序B. 堆排序C. 归并排序D. 直接插入排序5. 有一组数据(15,9,7,8,20,-1,7,4),用堆排序的筛选方法建立的初始堆为()A.-1,4,8,9,20,7,15,7 B.-1,7,15,7,4,8,20,9C.-1,4,7,8,20,15,7,9 D.A,B,C均不对。
6.在排序算法中每一项都与其它各项进行比较,计算出小于该项的项的个数,以确定该项的位置叫( )A.插入排序 B.枚举排序 C.选择排序 D.交换排序7.就排序算法所用的辅助空间而言,堆排序,快速排序,归并排序的关系是()A.堆排序〈快速排序〈归并排序 B.堆排序〈归并排序〈快速排序C.堆排序〉归并排序〉快速排序 D.堆排序 > 快速排序 > 归并排序8.在下列排序算法中,哪一个算法的时间复杂度与初始排序无关()。
A.直接插入排序 B. 气泡排序 C. 快速排序 D. 直接选择排序9.将两个各有N个元素的有序表归并成一个有序表,其最少的比较次数是( ) A.N B.2N-1 C.2N D.N-110.一组记录的关键码为(46,79,56,38,40,84),则利用快速排序的方法,以第一个记录为基准得到的一次划分结果为()。
A.(38,40,46,56,79,84) B. (40,38,46,79,56,84)C.(40,38,46,56,79,84) D. (40,38,46,84,56,79)11. 在下面的排序方法中,辅助空间为O(n)的是( ) 。
FORTRAN95第十章 排序、查找算法
给定值与处于顺序表“中间位置”上的元素的关键字进行比较键字则在表的后半部分继续进行二 分查找。否则在表的前半部分继续进行二分查找, 如此进行下去直 至找到满足条件的元素,或当前查找区为空。
10.1.4 直接插入排序 直接插入排序的方法是将待排记录分成两部分,初始第
一部分只含1个记录,在排序进程中把第二部分的全部记 录逐步插入到第一部分,并使该部分每次插入记录后是有 序的。直接插入排序算法步骤:
(1)将n个待排的记录数据存一维数组A中,默认A(1)为第 一部分的记录,2=>I;
(2)若I<=n, 则第二部分的一个记录A(I)与第一部分记 录进行比较, 找出在第一部分插入这个记录的位置,然后 将该位置上原来的记录及其后面所有的记录顺序后移一 个位置,在空出的位置上插入这个记录;若I>n (表示把 第二部分的记录全部插入到第一部分) ,则结束排序;
10.1.2 冒泡排序 冒泡排序是通过相邻两个排序记录的关键字的比
较,按一定次序互换逐步实现有序排序。 冒泡排序的实现过程是:第一次冒泡排序,首先将第
一个记录的关键字和第二个记录的关键字进行比较, 若不满足顺序的要求,则将两个记录进行交换,然
后比较第二个记录和第三个记录的关键字并做同样
处理,依次类推,直至对第n-1个记录和第n个记录 进行比较并处理完, 使得关键字值最大的记录被交换 到了最后一个记录的位置上。第二次冒泡排序只需
integer::low,high,key,ix,mid integer,dimension(low:high):: a do while(low<=high)
数据结构chapter_10
typedef struct { //定义每个记录 数据元素) 定义每个记录( //定义每个记录(数据元素)的结构 KeyType key ; //关键字 //关键字 InfoType otherinfo; //其它数据项 //其它数据项 }RedType; //记录类型 //记录类型 typedef struct { //定义顺序表 定义顺序表L //定义顺序表L的结构 RecordType r [ MAXSIZE +1 ]; //存储顺序表的向量 //存储顺序表的向量 //r[0] r[0]一般作哨兵或缓冲区 //r[0]一般作哨兵或缓冲区 int length ; //顺序表的长度 //顺序表的长度 }SqList; //顺序表类型 //顺序表类型
void BInsertSort (SqList &L) {
// 对顺序表 作折半插入排序 对顺序表L作折半插入排序 for ( i=2; i<=L.length; ++i ) { L.r[0] = L.r[i]; // 将L.r[i]暂存到 暂存到L.r[0] 暂存到 low = 1; high = i-1; while (low<=high) { // 在r[low..high]中折半查找有序插入的位置 中折半查找有序插入的位置 m = (low+high)/2; // 折半 if (L.r[0].key < L.r[m].key) high = m-1; // 插入点在低半区 else low = m+1; // 插入点在高半区 } // while for ( j=i-1; j>=low; --j ) L.r[j+1] = L.r[j]; // 记录后移 // 插入 L.r[high+1] = L.r[0]; } } // BInsertSort
数据结构Ch10习题答案
第十章内部排序一、择题1.用直接插入排序法对下面四个表进行(由小到大)排序,比较次数最少的是(B)。
A.(94,32,40,90,80,46,21,69)插32,比2次插40,比2次插90,比2次插80,比3次插46,比4次插21,比7次插69,比4次B.(21,32,46,40,80,69,90,94)插32,比1次插46,比1次插40,比2次插80,比1次插69,比2次插90,比1次插94,比1次C.(32,40,21,46,69,94,90,80)插40,比1次插21,比3次插46,比1次插69,比1次插94,比1次插90,比2次插80,比3次D.(90,69,80,46,21,32,94,40)插69,比2次插80,比2次插46,比4次插21,比5次插32,比5次插94,比1次插40,比6次2.下列排序方法中,哪一个是稳定的排序方法(BD)。
A.希尔排序B.直接选择排序C.堆排序D.冒泡排序下列3题基于如下代码:for(i=2;i<=n;i++){ x=A[i];j=i-1;while(j>0&&A[j]>x){ A[j+1]=A[j];j--;}A[j+1]=x}3.这一段代码所描述的排序方法称作(A)。
A.插入排序B.冒泡排序C.选择排序D.快速排序4.这一段代码所描述的排序方法的平均执行时间为(D)A.O(log2n) B.O(n) C.O(nlog2n) D.O(n2)5.假设这段代码开始执行时,数组A中的元素已经按值的递增次序排好了序,则这段代码的执行时间为(B)。
A.O(log2n) B.O(n) C.O(nlog2n) D.O(n2)6.在快速排序过程中,每次被划分的表(或了表)分成左、右两个子表,考虑这两个子表,下列结论一定正确是(B)。
A.左、右两个子表都已各自排好序B.左边子表中的元素都不大于右边子表中的元素C.左边子表的长度小于右边子表的长度D.左、右两个子表中元素的平均值相等7.对n个记录进行堆排序,最坏情况下的执行时间为(C)。
第十章 内部排序1
0 1 2 3 4 5 6 i=1 7 (49 38 65 97 76 13 27 ) i=2 38 (38 49) 65 97 76 13 27 i=3 65 (38 49 65) 97 76 13 27 i=4 97 (38 49 65 97) 76 13 27 i=5 76 (38 49 65 76 97) 13 27 i=6 13 (13 38 49 65 76 97) 27
k’1≤k’2≤···≤k’n 或 k’1≥k’2≥···≥k’n
• 稳定与不稳定:若记录序列中的任意两个记录 Rx , Ry 的排序码 Kx= Ky ;如果在排序之前和排 序之后,它们的相对位置保持不变,则这种排序 方法是稳定的,否则是不稳定的 • 排序中的两种基本操作:
– 两个排序码的比较(通常是必须的)
n
0
1 2 3 4 97 76 65 49
5 6 7 38 27 13
若待排序记录是随机的,取平均值
排序码比较次数:
n2 4
n2 记录移动次数: 4
时间复杂度:T(n)=O(n² ) 空间复杂度:S(n)=O(1)
10.1.2 折半插入排序
• 对直接插入排序,在插入记录Ri时,改用折半查找 方法确定插入的位置 • 算法思想:在插入Ri时,前面的记录R1, R2 ,·· Ri -1 ·, 已经排好序,因此可用折半查找找到Ri的插入位置
算法描述 #define M 100 //最大记录个数 typedef struct { int key; //排序码域 ···· //其他域 · ·; }RcdType; //记录类型 typedef RcdType Rcdlist[M+1];
//用顺序表存放,记录0下标不用 假设Rcdlist R;排序前待排序的记录已顺序存放在 R中,记录个数为n i:排序趟数,j:移动次数,直接插入排序算法如下:
数据结构第十、十一章:排序
14
9.2 交换排序
冒泡排序
排序过程
将第一个记录的关键字与第二个记录的关键字进行比较, 将第一个记录的关键字与第二个记录的关键字进行比较,若 为逆序r[1].key>r[2].key,则交换;然后比较第二个记录与 为逆序 ,则交换; 第三个记录;依次类推,直至第n-1个记录和第 个记录比较 个记录和第n个记录比较 第三个记录;依次类推,直至第 个记录和第 为止——第一趟冒泡排序,结果关键字最大的记录被安置在 第一趟冒泡排序, 为止 第一趟冒泡排序 最后一个记录上 对前n-1个记录进行第二趟冒泡排序,结果使关键字次大的 个记录进行第二趟冒泡排序, 对前 个记录进行第二趟冒泡排序 记录被安置在第n-1个记录位置 记录被安置在第 个记录位置 重复上述过程,直到“ 重复上述过程,直到“在一趟排序过程中没有进行过交换记 录的操作” 录的操作”为止
按待排序记录所在位置
内部排序: 内部排序:待排序记录存放在内存 外部排序: 外部排序:排序过程中需对外存进行访问的排序
稳定排序和不稳定排序 假设Ki=Kj(1≤i≤n,1≤j≤n,i≠j),且在排序前的序列中Ri领先 假设 ( , , ),且在排序前的序列中 领先 ),且在排序前的序列中 于Rj(即i<j)。若在排序后的排序中Ri仍领先于 ,即那些具 ( )。若在排序后的排序中 仍领先于Rj, )。若在排序后的排序中 仍领先于 有相同关键字的记录,经过排序后它们的相对次序仍然保持不变, 有相同关键字的记录,经过排序后它们的相对次序仍然保持不变, 则称这种排序方法是稳定的;反之,若Rj领先于 ,则称所用的 则称这种排序方法是稳定的;反之, 领先于Ri, 领先于 方法是不稳定的。 方法是不稳定的。 按排序依据原则
4
例
10排序1
1,排序所需的时间开销 排序所需的时间开销 主要是指执行排序时对关键字 比较次数和记录的移动次数. 和记录的移动次数 的比较次数和记录的移动次数. 2,排序所需的附加空间的开销 排序所需的附加空间的开销 附加空间
10.2 插入排序
插入排序总的基本思想: 插入排序总的基本思想:
每次将一个待排序的记录, 每次将一个待排序的记录, 按其关键字大小插入到一个已经排 好序(不减次序或不增次序) 好序(不减次序或不增次序)的文 件中适当的位置, 件中适当的位置,直到全部记录插 入完毕为止. 入完毕为止.
K i= K j, i > j
稳定排序: 稳定排序: 不稳定排序: 不稳定排序:
排序后
R i 领先R 领先R R j 领先R 领先R
j i
排序后具有相同关键字的记 录之间的相对次序 相对次序保持不变 录之间的相对次序保持不变
5,排序的分类
内部排序: 1. 内部排序:
排序中,文件只在内存中进行的排序. 排序中,文件只在内存中进行的排序. 2,外部排序: 外部排序: 排序中,文件不单要使用内存, 排序中,文件不单要使用内存, 而且使用外存的排序. 而且使用外存的排序.
10.2.1
直接插入排序
例如: 例如:已知一个无序文件记录的关键字序列 49,38,65,97,76,13,27, 为:49,38,65,97,76,13,27,49
以直接插入排序方法进行不减次序排序的过程为: 以直接插入排序方法进行不减次序排序的过程为: 不减次序排序的过程为 49,38,65,97,76,13,27,49 , , , , , , ,
27 27 27 27 27 97 97 76
49 49 49 49 49 49 49 97
内部排序习题
第10章内部排序【例10-1】已知关键字序列(12,77,21,65,38,7,38,53),给出采用直接插入排序方法按关键字递增序排列时的每一趟结果。
解:初始1趟2趟3趟4趟5趟6趟7趟(表示有序区)【例10-2】待排序列为(39,80,76,41,13,29,50,78,30,11,100,7,41,86),步长因子分别取5、3、1,给出采用希尔排序方法按关键字递增序排列时的每一趟结果。
解:排序过程如下:p=539 80 76 41 13 29 50 78 30 11 100 7 41 86子序列分别为{39,29,100},{80,50,7},{76,78,41},{41,30,86},{13,11}。
第一趟排序结果:p=3 29 7 41 30 11 39 50 76 41 13 100 80 78 86子序列分别为{29,30,50,13,78},{7,11,76,100,86},{41,39,41,80}。
第二趟排序结果:p=1 13 7 39 29 11 41 30 76 41 50 86 80 78 100此时,序列基本“有序”,对其进行直接插入排序,得到最终结果:7 11 13 29 30 39 41 41 50 76 78 80 86 100【例10-3】已知序列(17,18,60,40,7,32,73,65,85),请给出采用冒泡排序法对该序列作升序排序时的每一趟的结果。
解:初始1趟2趟3趟4趟5趟17 17 17 17 7 718 18 18 7 17 1760 40 7 18 18 1840 7 32 32 32 327 32 40 40 40 4032 60 60 60 60 6073 65 65 65 65 6565 73 73 73 73 7385 85 85 85 85 85(表示有序区)【例10-4】已知关键字序列(38,12,21,77,65,7,38,53)给出采用快速排序方法按关键字增序排序时的第一趟快排过程,并举出一个反例说明快速排序是不稳定排序。
DS10_排序01_概述和插入排序
排序
先迚排序方法,其时间复杂度为O(nlogn)
基数排序,其时间复杂度为O(d·n)
内排序的分类
按排序过程中依据的原则分
揑入类(直揑排序、二分排序、希尔排序) 交换类(冒泡排序、快速排序) 排序
选择类(直选排序、树型排序、堆排序)
归并类(二路归并排序、多路归并排序) 分配类(多关键字排序、基数排序)
3)折半插入排序性能分析
折半揑入排序减少了关键字的比较次数,但记彔的移动次数丌变,其 时间复杂度不直接揑入排序相同。
折半揑入排序是“稳定的”
3. 2-路插入排序
1)基本思想 2-路揑入排序是在折半揑入排序的基础上改迚的,目的是减少排序过 程中移动记彔的次数,但为此需要n个记彔的辅助空间。
2)具体做法
2)折半插入排序算法
void BinsertSort(SqList &L){ int i,low,high,mid; for(i=2; i<= L.length; ++i) { L.r[0]=L.r[i]; low=1; high=i-1; While(low<=high) { mid=(low+high)/2; if (L.r[0].key< L.r[mid].key) high=mid-1; else low=mid+1; } for( j=i-1; j>=low; j ) L.r[j+1]=L.r[j]; L.r[low]=L.r[0]; } }
另设一个和 L.r 同类型的数组d,首先将 L.r[1] 赋值给 d[1] ,并将 d[1] 看成是在排好序的序列中处于中间位置的记彔,然后从 L.r 中第 2 个记彔起依次揑入到d[1] 之前或之后的有序序列中。先将待揑入记彔的 关键字和 d[1] 的关键字迚行比较。 若 L.r[i]<d[1].key,则将 L.r[i] 揑入到 d[1] 之前的有序表中。反之, 揑入到 d[1] 之后的有序表中。
数据结构第十章 排序
10.2 插入排序 插入排序
直接插入排序 折半插入排序 2-路插入排序 表插入排序 希尔排序
10.2.1 直接插入排序
基本操作:将一个记录插入到已排好序的有序表中, 从而得到一个新的、记录数增1的有序表。
例:有一组待排序的记录的关键字初始序列如下:
(49,38,65,97,76,13,27,49`)
(4)归并排序 (5)基数排序
按内排过程中所需的工作量分类:
(1)简单的排序方法,其时间复杂度为O(n×n)
(2)先进的排序方法,其时间复杂度为O(nlogn);
(3)基数排序,其时间复杂度为O(d(n+rd))
排序算法的两种基本操作:
(1)比较两个关键字的大小; (2)将记录从一个位置移至另一个位置;
算法实现的关键设计:
将d看成是一个循环数组,并设两个指针first和final分别指示排序过 程中得到的有序序列中的第一个记录和最后一个记录在d中的位置.
例:有一组待排序的记录的关键字初始排列如下:
(49,38,65,97,76,13,27,49`) 16
[初始关键字] 49 38 65 97 76 13 27 49`
18
10.2.3 希尔排序 从直接插入排序
待排序序列基本有序可提高效率 回顾 待排序序列的记录数n很小时可提高效率
希尔排序的基本思想:
先将整个待排记录序列分割成为若干子序列分别进行
直接插入排序,待整个序列中的记录“基本有序”时,再对 全
体记例录:有进一行组一待次排直序接的插记入录排的序关. 键字初始排列如下: (49,38,65,97,76,13,27,49`)
} 12
直接插入排序的性能分析: 10. 3
(1)空间:只需一个记录的辅助空间r[0].
数据结构 使用C语言版 朱战立丛书版本 排序
2.堆排序
基本思想:把待排序的数据元素集合构成一个完全二叉树结 构,则每次选择出一个最大(或最小)的数据元素只需比较完 全二叉树的高度次,即log2n次,则排序算法的时间复杂度就是 O(nlog2n)。 一、堆的定义 堆分为最大堆和最小堆两种。定义如下: 设数组 a中存放了 n个数据元素,数组下标从 0开始,如果当数 组下标 2 i+1<n 时有 : a[i].key≥a[2i+1].key(a[i].key≤a[2i+1].key); 如 果 当 数 组 下 标 2 i+2<n 时 有 : a[i].key≥a[2i+2].key (a[i].key≤a[2i+2].key),则这样的数据结构称为最大堆 ( 最小堆 ) 。
较小时,尽量调整元素序列使之接近有序。这样,当数据元素个
数n为全部元素时,数据元素序列已比较接近有序。从而,整体 的时间效率会好很多。
算法如下:
void ShellSort (DataType a[], int n, int d[], int numOfD) //用希尔排序法对元素a[0]--a[n-1]排序,d[0]--d[numOfD-1]为希尔增量值 { int i, j, k, m, span; DataType temp; for(m = 0; m < numOfD; m++) //共numOfD次循环 { span = d[m]; //取本次的增量值 for(k = 0; k < span; k++) //共span个小组 { //组内是直接插入排序,区别是每次不是增1而是增span for(i = k; i < n-span; i = i+span) { temp = a[i+span]; j = i; while(j > -1 && temp.key < a[j].key) { a[j+span] = a[j]; j = j-span; } a[j+span] = temp; } } } }
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
最坏的情况(关键码在记录序列中逆序有序):
“比较”次数为(n+2)(n-1)/2 ,“移动”次数为(n+4)(n-1)/2 总的说来,直接插入排序所需进行关键码间的比较次数和记录移动次数均
为n2/4,所以直接插入排序的时间复杂度为O(n2)。 空间效率:需要一个记录的辅助空间,因此空间复杂度为O(1)
性能分析: 时间效率 最好的情况只需进行一趟起泡:“比较”次数为n-1,“移动”次数为0
最坏的情况需进行n-1趟起泡:“比较”的次数为
数与“比较”的次数 相同 。 “移动”次数是“交换”次数的 3倍 所以时间复杂度为:O(n2)—因为要考虑最坏情况
“交换”次
空间效率: O(1)—只在交换时用到一个缓冲单元 稳定性:稳定的
10.3.2 快速排序 基本思想:任取待排序序列中的某个元素作为基准(一般取第一个 元素),通过一趟排序,将待排元素分为左右两个子序列,左子序列元
素的排序码均小于基准元素的排序码,右子序列的排序码则大于等于基
准元素的排序码,然后分别对两个子序列继续进行排序,直至整个序列 有序。 例子:初始序列
第1次交换后 第2次交换后 第3次交换后 第4次交换后 完成一趟排序 【 46 i 【 17 i 【 17 【 17 【 17 【 17 i 05 i 05 05 13 13 42 55 i 13 13 42 42 94 94 i j 94 55 55 70 】 70 】 05 j 13 42 94 05 j 55 j 55 70 】 70 】 基准元素 55 13 42 94 05 17 j 70 】 j 70 】
例子: 初态
第一趟结果 第二趟结果
[49 38 65 97 76 13 27 49] 13[38 65 97 76 49 27 49] 13 27[65 97 76 49 38 49]
第三趟结果
13 27 38[97 76 49 65 49]
第四趟结果 13 27 38 49[76 97 65 49] 第五趟结果 13 27 38 49 49[97 65 76]
第1趟 (kd=5) 第2趟 (kd=3) 第3趟 (kd=1) 算法(略) 性能分析 :
0
1 49
49 13 13 13 04
2 38
38 27 27 04 04 13
3 65
65 49* 49* 49* 27
4 97
97 55 55 38 38
5 76
76 04 04 27 27 49*
6 13
例子:关键字序列 T=(21,25,49,25*,16,08)
请写出冒泡排序的具体实现过程。
初态: 第1趟 第2趟 第3趟 第4趟 第5趟
21
25 49
21 25 25*
21 25
21 08
16 08
08 16
16
08 25* 49
16
25 25* 49
21
25 25* 49
21
25 25* 49
插入排序的方法:直接插入排序、折半插入排序、2-路插入排序、表
插入排序和希尔排序。 10.2.1 直接插入排序
新元素插入到哪里? 在已形成的有序表中线性查找,并在适当位置插 入,把原来位置上的元素向后顺移。
例1:关键字序列T=(13,6,3,31,9,27,5,11), 请写出直接插入排序的中间过程序列。
【13】, 6, 3, 31, 9, 27, 5, 11
【6, 13】, 3, 31, 9, 27, 5, 11
【3, 6, 13】, 31, 9, 27, 5, 11 【3, 6, 13,31】, 9, 27, 5, 11 【3, 6, 9, 13,31】, 27, 5, 11 【3, 6, 9, 13,27, 31】, 5, 11 【3, 5, 6, 9, 13,27, 31】, 11 【3, 5, 6, 9, 11,13,27, 31】
i j j 42 】 46 【94
算法:
int partition(SqList &L,int low,int high){
L.r[0]=L.r[low] ; //用子表的第一个记录作枢轴记录
pivotkey=L.r[low].key; //枢轴记录关键字 while(low<high){ --high; L.r[low]=L.r[high] ; //将比枢轴记录小的记录移到低端 while(low<high &&L.r[low].key<=pivotkey) //从表两端交替地向中间扫描 while(low<high &&L.r[high].key>=pivotkey)
…
{ R[d],R[2d],R[3d],…,R[kd],R[(k+1)d] }
其中,d 称为增量,它的值在排序过程中从大到小逐渐缩小,直至最后一
趟排序8,65,97, 76, 13, 27, 49*,55, 04), 请写出希尔排序的具体实现过程。
r[i] 初态:
}
性能分析:
时间复杂度为O(nlog2n)
空间复杂度为O(1) 稳定性:不稳定的
例如:若对21,25,49,25*,16,08进行快速排序后,25*跑到了25的前面。
10.4 选择排序
每一趟从待排序的记录中选出关键码最小的记录,顺序放在已排好序
的子序列的最后,直到全部记录排序完毕。 选择排序的方法:简单选择排序、树形选择排序、堆排序。 10.4.1 简单选择排序 基本思想:扫描整个线性表,从中选出最小的元素,将它交换到 表的最前面;然后对剩下的子表采用同样的方法,直到子表空为止。
L.r[j+1]=L.r[j];// 记录后移 L.r[j+1]=L.r[0];// 插入到正确位置 } }
性能分析:
时间效率 实现排序的基本操作有两个: (1)“比较”序列中两个关键码的大小;(2)“移动”记录。 对于直接插入排序: 最好的情况(关键码在记录序列中顺序有序): “比较”次数为n-1 ,“移动”次数为0
第六趟结果
第七趟结果
13 27 38 49 49 65[97 76]
13 27 38 49 49 65 76 97
算法: void SelectSort(SqList &L)
{ //简单选择排序 for (i=1; i<L.length; ++i) { //在L.r[i..L.length] 中选择key最小的记录
算法: void Insertsort(SqList &L) { for(i=2;i<=L.length;i++)
if(LT(L.r[i]).key,L.r[i-1].key)
{ L.r[0]=L.r[i];// 监视哨
for(j=i-1;LT(L.r[0].key,L.r[j].key;j--)
第10章 内部排序
10.1 概述
相关术语
1.排序:是计算机内经常进行的一种操作,其目的是将一组“无序”的记 录序列调整为“有序”的记录序列。 2. 排序码:作为排序依据的数据项,也即数据元素的关键码。 3. 排序算法的稳定性:是指对于两个关键码相等的记录,它们在序列中的 相对位置,在排序之前和经过排序之后,没有改变。 4. 内部排序和外部排序:若整个排序过程不需要访问外存便能完成,则称
此类排序问题为内部排序;反之,若参加排序的记录数量很大,整个序列
的排序过程不可能在内存中完成,则称此类排序问题为外部排序。在本章 内我们只讨论内部排序的各种方法。
5. 内部排序的方法:插入排序、交换排序、选择排序、归并排序、基数排
序等。
10.2 插入排序
每次将一个待排序的记录,按其关键码大小插入到前面已排好序的子 序列的适当位置,直到全部记录插入为止。
low = 1; high = i-1; while (low<=high) { //在r[low..high]中折半查找插入的位置 m = (low+high)/2; // 折半 if (LT(L.r[0].key,L.r[m].key)) high = m-1; // 插入点在低半区 else low = m+1; // 插入点在高半区 } for ( j=i-1; j>=high+1; --j ) L.r[j+1] = L.r[j]; // 记录后移 L.r[high+1] = L.r[0]; // 插入 } } // BInsertSort
性能分析: 时间效率
折半插入排序比直接插入排序明显地减少了关键码间的“比较”
次数,但记录“移动”的次数不变。因此,时间复杂度为O(n2) 空间效率:也只需要一个记录的辅助空间,因此空间复杂度也为O(1) 稳定性:稳定的。
10.2.3 希尔排序(又称缩小增量排序)
基本思想:对待排记录序列先作“宏观”调整,然后再作“微观”调整。 所谓“宏观”调整:指的是“跳跃式”的插入排序。具体做法为: 将记录序列分成若干子序列,分别对每个子序列进行插入排序。 所谓“微观”调整:指的是对 “基本有序”的全体记录再作最后进行一次 直接插入排序 例如:将 n 个记录{R[1]…R[n]}分成 d 个子序列: { R[1],R[1+d],R[1+2d],…,R[1+kd] } { R[2],R[2+d],R[2+2d],…,R[2+kd] }
k=i; for( j=i+1;j<=L.length ; j++) if ( L.r[j].key <L.r[k].key) k=j; if(k!=i) L.r[i]←→L.r[j];
} } //SelectSort
性能分析 : 时间效率:对n个记录进行简单选择排序,所需进行的关键码间的比较次