数据结构10-内部排序
数据结构-内排序
Shell排序的性能分析
Shell排序的时间复杂度在O(nlog2n)和O(n2)间, Knuth的 统计结论是,平均比较次数和记录平均移动次数在n1.25与 1.6n1.25之间
Shell排序是一种不稳定的排序方法
最后谈一下delta的取法。 Shell最初的方案是delta=n/2, delta=delta/2,直到delta=1。Knuth的方案是delta=delta/3 +1。其它方案有:都取奇数为好;或delta互质为好等等。 而使用象1, 2, 4, 8, …或1, 3, 6, 9, …这样的增量序列就不太 合适,因为这样会使几个元素多次被分到一组中,从而造 成重复排序,产生大量无用的比较操作
另外,在无序子表中向前移动的过程中,如果没 有交换元素,则说明无序子表已有序,无须再做 排序
24
冒泡排序算法实现
1 void bubble_sort(RecType R[ ], int n) { 2 //待排序元素用一个数组R表示,数组有n个记录
3 int i, j; 4 bool swap=TRUE; //判断无序子表是否已有序的变量
内排序和外排序 按照排序过程中使用内、外存的不 同将排序方法分为内排序和外排序。若待排序记录全 部在内存中,称为内排序;若待排序记录的数量很大, 以致内存一次不能容纳全部记录,在排序过程中需要 进行内、外存交换,称为外排序。本章仅讨论内排序
内排序可分为五大类:插入排序、交换排序、选择排 序、归并排序和基数排序
直接插入排序(straight insert sort) 折半插入排序(binary insert sort) Shell排序(Shell sort)
10
10.2.1 直接插入排序举例
严蔚敏 数据结构第十章 内部排序的具体代码(c++,附测试数据)
int exchange = 1;
SortData temp;
while ( i < n && exchange ){
exchange = 0; //标志置为0,假定未交换
for ( int j = n-1; j >= i; j-- )
QSort(L,1,L.length);
}//QuickSort
//**************************************************
//直接选择排序
void SelectSort ( SortData V[ ], int n ) {
for ( int i = 0; i < n-1; 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 )
L.r[j+1]=L.r[j];
L.r[j+1]=L.r[0];
//*******************************************
//直接插入排序
void InsertSort ( SqList &L ) {
//按非递减顺序对表进行排序,从后向前顺序比较
int i,j;
for ( i = 2; i <= L.length; ++ i)
low=1;high=i-1; //查找范围由1到i-1
while(low<=high){
数据结构-第十章-内部排序
0
1
2
3
4
5
6
7
8
i=5
MAXINT 49 2 3
MAXINT 49 6 3 MAXINT 49 6 3 MAXINT 49 6 8
38 1
38 1 38 1 38 1
65 97 5 0
65 5 65 5 65 5 97 0 97 0 97 0
76 4
76 4 76 4 76 4
13
27
49
i=6
最坏情况下,待排记录按关键字非递增有序 排列(逆序)时,第 i 趟时第 i+1 个对象 必须与前面 i 个对象都做排序码比较, 并且 每做1次比较就要做1次数据移动。总比较 次 数 为 (n+2)(n-1)/2 次 , 总 移 动 次 数 为 (n+4)(n-1)/2。 在平均情况下的排序码比较次数和对象移 动次数约为 n2/4。因此,直接插入排序的 时间复杂度为 O(n2)。 直接插入排序是一种稳定的排序方法。
折半插入排序 (Binary Insertsort)
基本思想 既然每个要插入记录之前的纪录 已经按关键字有序排列,在查找插入位 臵时就没有必要逐个关键字比较,可以 使用折半查找来实现。由此进行的插入 排序称之为折半插入排序。
折半插入排序的算法
void BInsertSort (SqList &L){ for (i=2;i<=L.length;++i){ L.r[0]=L.r[i]; low=1;high=i-1; //查找范围由1到i-1 while(low<=high){ m=(low+high)/2; if LT(L.r[0].key,L.r[m].key) high=m-1; else low=m+1; }//while 折半查找 for (j=i-1;j>=high+1;--j) L.r[j+1]=L.r[j]; //折半查找结束后high+1位臵即为插入位臵 L.r[high+1]=L.r[0]; }//for }//BInsertSort
数据结构答案 第10章 排序学习与指导
第10章排序10.1 知识点分析1.排序基本概念:(1)排序将数据元素的任意序列,重新排列成一个按关键字有序(递增或递减)的序列的过程称为排序。
(2)排序方法的稳定和不稳定若对任意的数据元素序列,使用某个排序方法,对它按关键字进行排序,若对原先具有相同键值元素间的位置关系,排序前与排序后保持一致,称此排序方法是稳定的;反之,则称为不稳定的。
(3)内排序整个排序过程都在内存进行的排序称为内排序,本书仅讨论内排序。
(4)外排序待排序的数据元素量大,以致内存一次不能容纳全部记录,在排序过程中需要对外存进行访问的排序称为外排序。
2.直接插入排序直接插入排序法是将一个记录插到已排序好的有序表中,从而得到一个新的,记录数增1的有序表。
3.二分插入排序二分插入排序法是用二分查找法在有序表中找到正确的插入位置,然后移动记录,空出插入位置,再进行插入的排序方法。
4.希尔排序希尔排序的基本思想是:先选取一个小于n的整数d1作为第一个增量,把待排序的数据分成d1个组,所有距离为d1的倍数的记录放在同一个组内,在各组内进行直接插入排序,每一趟排序会使数据更接近于有序。
然后,取第二个增量d2,d2< d1,重复进行上述分组和排序,直至所取的增量d i=1(其中d i< d i-1 < ……< d2< d1),即所有记录在同一组进行直接插入排序后为止。
5.冒泡排序冒泡法是指每相邻两个记录关键字比大小,大的记录往下沉(也可以小的往上浮)。
每一遍把最后一个下沉的位置记下,下一遍只需检查比较到此为止;到所有记录都不发生下沉时,整个过程结束。
6.快速排序快速排序法是通过一趟排序,将待排序的记录组分割成独立的两部分,其中前一部分记录的关键字均比枢轴记录的关键字小;后一部分记录的关键字均比枢轴记录的关键字大,枢轴记录得到了它在整个序列中的最终位置并被存放好。
第二趟再分别对分割成两部分子序列,再进行快速排序,这两部分子序列中的枢轴记录也得到了最终在序列中的位置而被存放好,并且它们又分别分割出独立的两个子序列……。
第十章_排序方法(数据结构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章
一、什么是排序?
排序是计算机内经常进行的一种操作, 其目的是将一组“无序”的记录序列调 整为“有序”的记录序列。
例如:将下列关键字序列 52, 49, 80, 36, 14, 58, 61, 23, 97, 75
调整为
14, 23, 36, 49, 52, 58, 61 ,75, 80, 97 .页 08.06.2020
10. 2 插入排序
.页 08.06.2020
一趟直接插入排序的基本思想:
有序序列R[1..i-1]
无序序列 R[i..n]
R[i]
有序序列R[1..i]
无序序列 R[i+1..n]
.页 08.06.2020
实现“一趟插入排序”可分三步进行:
1.在R[1..i-1]中查找R[i]的插入位置,
R[1..j].key R[i].key < R[j+1..i-1].key;
有序序列区 无 序 序 列 区
经过一趟排序
08.06.2020
有序序列区 无 序 序 列 区
.页
基于不同的“扩大” 有序序列长 度的方法,内部排序方法大致可分 下列几种类型:
插入类 交换类 选择类
归并类 其它方法
.页 08.06.2020
#待de排fin记e M录A的XS数IZ据E 类10型00定// 义待排如顺下序:表最大长度
第十章 排序
.页 08.06.2020
【课前思考】
1. 你熟悉排序吗?你过去曾经学过哪些排序方法? 在第一章中曾以选择排序和起泡排序为例讨论算 法实践复杂度,不知你还记得吗? 2. 你自己有没有编过排序的程序?是用的什么策 略?
.页 08.06.2020
【学习目标】
严蔚敏《数据结构》复习笔记及习题 (内部排序)【圣才出品】
第10章内部排序10.1 复习笔记一、概述1.排序的相关概念(1)排序:重新排列表中元素,使其按照关键字递增或递减排列的过程。
(2)内部排序:待排序记录存放在计算机的随机存储器中进行排序的过程。
(3)外部排序:待排序记录数据量大,内存不能一次性容纳全部记录,排序时需对外存进行访问的过程。
2.排序算法的评价(1)时间复杂度(2)空间复杂度(3)稳定性在设计排序算法时,除了考虑算法的时间和空间复杂度外,还需考虑算法的稳定性,稳定性定义如下:待排序列中两个元素R i,R j对应的关键字K i=K j,且排序前R i在R j前面,若选择某一种算法对该序列排序后,R i仍在R j前面,则称该排序算法是稳定的,否则是不稳定的。
二、插入排序1.直接插入排序(1)算法分析将待排序记录分为有序子序列和无序子序列两部分,每次将无序序列中的元素插入到有序序列中的正确位置上。
即:先将序列中的第1个记录看成是一个有序的子序列,然后从第2个记录起逐个进行插入,直至整个序列变成按关键字非递减的有序序列为止,整个排序过程进行n-1趟插入。
其算法实现如下:(2)算法评价①时间复杂度:平均情况下,考虑待排序列是随机的,其时间复杂度为O(n2)。
②空间复杂度:仅使用常数个辅助单元,空间复杂度为O(1)。
③稳定性:每次插入元素都是从后向前先比较再插入,不存在相同元素位置交换,所以算法是稳定的。
2.折半插入排序(1)算法分析当排序表顺序存储时,可以先折半查找出待插位置,再对该位置后的元素统一后移,并完成插入操作。
其算法实现如下:(2)算法评价①时间复杂度:折半插入排序只是减少了元素比较次数,其他的均与直接插入排序相同,因此时间复杂度仍为O(n2)。
②空间复杂度:与直接插入排序相同,为O(1)。
③稳定性:与直接插入排序相同,是稳定的算法。
3.希尔排序(1)算法分析先将整个待排记录序列分割成为若干子序列(形如L[i,i+d,i+2d,…,i+kd]),分别进行直接插入排序,待整个序列中的记录“基本有序”时,再对全体记录进行一次直接插入排序。
数据结构 排序
2019/9/7
30
10.4.1 简单选择排序
待排记录序列的状态为:
有序序列R[1..i-1] 无序序列 R[i..n]
有序序列中所有记录的关键字均小于无序序列中记 录的关键字,第i趟简单选择排序是从无序序列 R[i..n]的n-i+1记录中选出关键字最小的记录加入 有序序列
2019/9/7
5
排序的类型定义
#define MAXSIZE 20 // 待排序记录的个数
typedef int KeyType;
typedef struct
{ KeyType key;
InfoType otherinfo; ∥记录其它数据域
} RecType;
typedef struct {
RecType r[MAXSIZE+1];
分别进行快速排序:[17] 28 [33] 结束 结束
[51 62] 87 [96] 51 [62] 结束
结束
快速排序后的序列: 17 28 33 51 51 62 87 96
2019/9/7
26
自测题 4 快速排序示例
对下列一组关键字 (46,58,15,45,90,18,10,62) 试写出快速排序的每一趟的排序结果
final↑ ↑first
i=8
[51 51 62 87 96 17 28 33]
final↑ ↑first
2019/9/7
14
希尔(shell )排序
基本思想:从“减小n”和“基本有序”两 方面改进。
将待排序的记录划分成几组,从而减少参 与直接插入排序的数据量,当经过几次分 组排序后,记录的排列已经基本有序,这 个时候再对所有的记录实施直接插入排序。
数据结构复习题-第10章答案2014-6-16
第10章内部排序一、选择题(每小题1分,共10分)1.从未排序序列中依次取出一个元素与已排序序列中的元素依次进行比较,然后放在已排序序列的合适位置,该排序方法称为( A )排序法。
A.插入排序B.选择排序C.希尔排序D.二路归并排序2.下列排序算法中( C )排序在一趟结束后不一定能选出一个元素放在其最终位置上。
A.选择B.冒泡C.归并D.堆3.若一组记录的排序码为(46, 79, 56, 38, 40, 84),则利用快速排序的方法,以第一个记录为基准得到的一次划分结果为( C )。
A. 38, 40, 46, 56, 79, 84B. 40, 38, 46, 79, 56, 84C. 40, 38,46, 56, 79, 84D. 40, 38, 46, 84, 56, 794.排序方法中,从未排序序列中依次取出元素与已排序序列(初始时为空)中的元素进行比较,将其放入已排序序列的正确位置上的方法,称为( C )。
A.希尔排序B.冒泡排序C.插入排序D.选择排序5.为实现快速排序算法,待排序序列宜采用的存储方式是( A )。
A. 顺序存储B. 散列存储C. 链式存储D. 索引存储6.若一组记录的排序码为(46, 79, 56, 38, 40, 84),则利用堆排序的方法建立的初始堆为( B )。
A. 79, 46, 56, 38, 40, 84B. 84, 79, 56, 38, 40, 46C. 84, 79, 56, 46, 40, 38D. 84, 56, 79, 40, 46, 387.排序方法中,从未排序序列中依次取出元素与已排序序列中的元素进行比较,将其放入已排序序列的正确位置上的方法,称为( C )。
A.希尔排序B.冒泡排序C.插入排序D.选择排序8.在所有的排序方法中,关键字比较的次数与记录的初始排列次序无关的是( D )。
A.希尔排序B.冒泡排序C.直接插入排序D.直接选择排序9.堆是一种有用的数据结构。
《数据结构》期末考试复习题-第10章-排序
第10章排序一、选择题1.某内排序方法的稳定性是指( )。
【南京理工大学 1997 一、10(2分)】A.该排序算法不允许有相同的关键字记录 B.该排序算法允许有相同的关键字记录C.平均时间为0(n log n)的排序方法 D.以上都不对2.下面给出的四种排序法中( )排序法是不稳定性排序法。
【北京航空航天大学 1999 一、10 (2分)】A. 插入B. 冒泡C. 二路归并D. 堆积3.下列排序算法中,其中()是稳定的。
【福州大学 1998 一、3 (2分)】A. 堆排序,冒泡排序B. 快速排序,堆排序C. 直接选择排序,归并排序D. 归并排序,冒泡排序4.稳定的排序方法是()【北方交通大学 2000 二、3(2分)】A.直接插入排序和快速排序 B.折半插入排序和起泡排序C.简单选择排序和四路归并排序 D.树形选择排序和shell排序5.下列排序方法中,哪一个是稳定的排序方法?()【北方交通大学 2001 一、8(2分)】A.直接选择排序 B.二分法插入排序 C.希尔排序 D.快速排序6.若要求尽可能快地对序列进行稳定的排序,则应选(A.快速排序 B.归并排序 C.冒泡排序)。
【北京邮电大学 2001 一、5(2分)】7.如果待排序序列中两个数据元素具有相同的值,在排序前后它们的相互位置发生颠倒,则称该排序算法是不稳定的。
()就是不稳定的排序方法。
【清华大学 1998 一、3 (2分)】A.起泡排序 B.归并排序 C.Shell排序 D.直接插入排序 E.简单选择排序8.若要求排序是稳定的,且关键字为实数,则在下列排序方法中应选()排序为宜。
A.直接插入 B.直接选择 C.堆 D.快速 E.基数【中科院计算所 2000 一、5(2分)】9.若需在O(nlog2n)的时间内完成对数组的排序,且要求排序是稳定的,则可选择的排序方法是()。
A. 快速排序B. 堆排序C. 归并排序D. 直接插入排序【中国科技大学 1998 二、4(2分)】【中科院计算所 1998 二、4(2分)】10.下面的排序算法中,不稳定的是()【北京工业大学 1999 一、2 (2分)】A.起泡排序B.折半插入排序C.简单选择排序D.希尔排序E.基数排序F.堆排序。
数据结构第10章排序练习及答案
9.1选择题1.从末排序的序列中依次取出一个元素与已排序序列中的元素依次进行比较,然后将其放在排序序列的合适位置,该排序方法称为()排序法。
A)插入B)选择C)希尔D)二路归并【答案】A2.下面各种排序方法中,最好情况下时间复杂度为O(n)的是()A)快速排序B)直接插入排序C)堆排序D)归并排序【答案】B3.用某种排序方法对线性表(25,84,21,47,15,27,68,35,20)进行排序时,无序序列的变化情况如下:25 84 21 47 15 27 68 35 2020 15 21 25 47 27 68 35 8415 20 21 25 35 27 47 68 8415 20 21 25 27 35 47 68 84则所采用的排序方法是()A)选择排序B)希尔排序C)归并排序D)快速排序【答案】D4.下面给出的四种排序法中,()排序是不稳定排序法。
A)插入B)冒泡C)二路归并D)堆【答案】D5.快速排序方法在()情况下最不利于发挥其长处。
A)要排序的数据量太大B)要排序的数据中含有多个相同值C)要排序的数据已基本有序D)要排序的数据个数为奇数【答案】C6.一组记录的关键码为(46,79,56,38,40,84),则利用快速排序的方法,以第一个记录为基准得到的一次划分结果为()A)38,40,46,56,79,84B)40,38,46,79,56,84C)40,38,46,56,79,84D)40,38,46,84,56,79【答案】C7.对记录的关键码{50,26,38,80,70,90,8,30,40,20}进行排序,各趟排序结束时的结果为:50,26,38,80,70,90 ,8,30,40,2050,8,30,40,20,90,26,38,80,7026,8,30,40,20,80,50,38,90,708,20,26,30,38,40,50,70,80,90其使用的排序方法是()A)快速排序B)基数排序C)希尔排序D)归并排序【答案】C8.以下序列不是堆的是()A)100,85,98,77,80,60,82,40,20,10,66B)100,98,85,82,80,77,66,60,40,20,10C)10,20,40,60,66,77,80,82,85,98,100D)100,85,40,77,80,60,66,98,82,10,20【答案】D【解析】根据堆采用完全二叉树的顺序存储形式及堆的特点,因第一个结点即根结点关键字值最大,则应建立一个大根堆,但依据此数据序列建立起堆后关键字值为40的左右孩子结点分别为60、66,不符合大根堆特点。
数据结构使用C语言版朱战立丛书版本排序
{ 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>
优点:实现简单
缺点:每趟只能确定一个元素,表长为n时需要n-1趟
算法如下:
void SelectSort<DataType a[], int n>
{
int i, j, small;
DataType temp;
for<i = 0; i < n-1; i++>
{ small = i;
//设第i个数据元素关键字
(a)初始最大堆 40
32
9
5
10
40 32 9 5 10 50 76 88 (d)交换顶点50后 9
5
76
50
40
5
10
9
32
76 50 40 5 10 9 32 88 (b)交换顶点88后 32
10
9
5
32 10 9 5 40 50 76 88 (e)交换顶点40后
5
9 5 10 32 40 50 76 88
{ a[j+span] = a[j];
j = j-span;
65
数据结构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)。
数据结构单元10练习参考答案
单元测验10一.判断题(下列各题,正确的请在前面的括号内打√;错误的打╳)(ㄨ)(1)如果某种排序算法不稳定,则该排序方法就【没】有实用价值。
(√)(2)希尔排序是不稳定的排序。
(ㄨ)(3)冒泡排序是【不】稳定的排序。
(√)(4)对n个记录的进行快速排序,所需要的平均时间是O(nlog2n)。
(ㄨ)(5)堆排序所需的时间与待排序的记录个数【无】有关。
(√)(6)当待排序的元素个数很多时,为了交换元素的位置要占用较多的时间,这是影响时间复杂度的主要因素。
(ㄨ)(7)快速排序不是在任何情况下都比其它排序方法速度快。
(√)(8)对快速排序来说,初始序列为正序或反序都是最坏情况。
(√)(9)采用归并排序可以实现外排序。
(√)(10)采用希尔方法排序时,若关键字的排列杂乱无序,则效率最高(√)(11)快速排序算法在每一趟排序中都能找到一个元素放在其最终位置上。
(√)(12)冒泡排序的时间复杂度是O(n2)。
二.填空题(1)大多数排序算法都有两个基本的操作:比较和移动。
(2)评价排序算法优劣的主要标准是时间复杂度和算法所需的附加空间。
(3)根据被处理的数据在计算机中使用不同的存储设备,排序可分为:内排序和外排序。
(4)外排序是指在排序过程中,数据的主要部分存放在计算机的外存中。
(5)对n个关键字进行冒泡排序,其可能的最小比较次数为:n-1次。
(6)在最坏情况下,在第i趟直接插入排序中,要进行i-1次关键字的比较。
(7)对n个关键字进行冒泡排序,时间复杂度为 O(n2) 。
(8)快速排序在最坏情况下的时间复杂度是 O(n2) 。
(9)对于n个记录的集合进行归并排序,所需要的平均时间为: O(log2n) 。
(10)对于n个记录的集合进行归并排序,所需要的附加空间是 O(n) 。
(11)若原始数据接近无序,则选用快速排序最好。
(12)在排序前,关键字值相等的不同记录,排序后相对位置保持不变的排序方法,称为稳定排序方法。
数据结构第十、十一章:排序
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
例
《数据结构与算法》第十章-排序习题
《数据结构与算法》第二部分习题精选一、填空题1. 大多数排序算法都有两个基本的操作:和。
2. 在对一组记录(54,38,96,23,15,72,60,45,83)进行直接插入排序时,当把第7个记录60插入到有序表时,为寻找插入位置至少需比较次。
(可约定为从后向前比较)3. 在插入和选择排序中,若初始数据基本正序,则选用;若初始数据基本反序,则选用。
4. 在堆排序和快速排序中,若初始记录接近正序或反序,则选用;若初始记录基本无序,则最好选用。
5. 对于n个记录的集合进行冒泡排序,在最坏的情况下所需要的时间是。
若对其进行快速排序,在最坏的情况下所需要的时间是。
6. 对于n个记录的集合进行归并排序,所需要的平均时间是,所需要的附加空间是。
7.对于n个记录的表进行2路归并排序,整个归并排序需进行趟(遍),共计移动次记录。
二、单项选择题()1.将5个不同的数据进行排序,至多需要比较次。
A. 8 B. 9 C. 10 D. 25()2.排序方法中,从未排序序列中依次取出元素与已排序序列(初始时为空)中的元素进行比较,将其放入已排序序列的正确位置上的方法,称为A. 希尔排序B. 冒泡排序C. 插入排序D. 选择排序()3.排序方法中,从未排序序列中挑选元素,并将其依次插入已排序序列(初始时为空)的一端的方法,称为A. 希尔排序B. 归并排序C. 插入排序D. 选择排序()4.对n个不同的排序码进行冒泡排序,在下列哪种情况下比较的次数最多。
A. 从小到大排列好的B. 从大到小排列好的C. 元素无序D. 元素基本有序()5.对n个不同的排序码进行冒泡排序,在元素无序的情况下比较的次数为A. n+1 B. n C. n-1 D. n(n-1)/2 ()6.快速排序在下列哪种情况下最易发挥其长处。
A. 被排序的数据中含有多个相同排序码B. 被排序的数据已基本有序C. 被排序的数据完全无序D. 被排序的数据中的最大值和最小值相差悬殊()7.对有n个记录的表作快速排序,在最坏情况下,算法的时间复杂度是A.O(n) B.O(n2) C.O(nlog2n) D.O(n3)()8.若一组记录的排序码为(46, 79, 56, 38, 40, 84),则利用快速排序的方法,以第一个记录为基准得到的一次划分结果为A. 38, 40, 46, 56, 79, 84 B. 40,38, 46 , 79, 56, 84C. 40, 38,46, 56, 79, 84 D. 40, 38,46, 84, 56, 79()9.在最好情况下,下列排序算法中排序算法所需比较关键字次数最少。
严蔚敏版《数据结构(C语言版)》-内部排序-第10章
high=mid-1 ; else low=mid+1 ;
}
/* 查找插入位置 */
for (j=i-1; j>=high+1; j--)
L->R[j+1]=L->R[j];
L->R[high+1]=L->R[0]; /* 插入到相
应位置 */
}
}
从时间上比较,折半插入排序仅仅减少了关键字的 比较次数,却没有减少记录的移动次数,故时间复杂度 仍然为O(n2) 。
待排序的记录类型的定义如下:
#define MAX_SIZE 100
Typedef int KeyType ;
typedef struct RecType
{ KeyType key ;
/* 关键字码 */
infoType otherinfo ; /* 其他域 */
}RecType ;
typedef struct Sqlist
③ 记录存储在一组连续地址的存储空间:构造另一 个辅助表来保存各个记录的存放地址(指针) :排序 过程不需要移动记录,而仅需修改辅助表中的指针, 排序后视具体情况决定是否调整记录的存储位置。
①比较适合记录数较少的情况;而②、③则适合 记录数较少的情况。
为讨论方便,假设待排序的记录是以①的情况存 储,且设排序是按升序排列的;关键字是一些可直接用 比较运算符进行比较的类型。
(n-1)(n+1)
2
移动次数:∑n (i+1)=
i=2
(n-1)(n+4)
2
一般地,认为待排序的记录可能出现的各种排列的
概率相同,则取以上两种情况的平均值,作为排序的关
数据结构第十章 排序
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].
数据结构课程的内容
空间效率: O(1) 稳定性:稳定
23
折半插入排序算法
void BiInsertSort(SqList *L)
{ int i,j, low,high,m;
for(i=2;i<=L->length;i++)
{ L->r[0]=L->r[i]; low=1; high=i-1;
(KCN)和对象移动次数(RMN)分别为:
比较次数:n i = (n +2)(n -1)
i=2
2
移动次数:n(i +1)= (n +4)(n -1)
i=2
2
时间复杂度为O(n2)。
54 32 1 44 5 3 2 1 33 4 5 2 1 22 3 4 5 1 11 2 3 4 5
比较i次(依次与前面的i-1个记录进行比较,并和哨兵比较1次),移动i+1次(前面的i-1个记录依次向后移动,另外开始 19
13
*表示后一个25
例2:关键字序列T= (21,25,49,25*,16,08),
请写出直接插入排序的具体实现过程。 解:假设该序列已存入一维数组V[7]中,将V[0]作为缓冲或
暂存单元(Temp)。则程序执行过程为:
初态:
完成!
22410暂存59685*
021816
21516
2425951*
2459*
定义:
设有记录序列:{ R1、R2………Rn } 其相应的 关键字序列为: { K1、K2………Kn }; 若存在一种 确定的关系:Kx<=Ky<=…<= Kz则将记录序列 { R1、 R2……….Rn}排成按该关键字有序的序列: { Rx、 Ry……….Rz}的操作,称之为排序。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
想进行的排序:将相邻记录两两分为一组进行比较, 将关键字较小的记录送往上一层,参加与其它组关 键字较小记录的比较,两两比较后再送往上层关键 字较小记录,反复此过程,直到只剩下一个记录即 为关键字最小记录;将待排序列中该最小记录处置 为无穷大,则与其比较过的所有记录按层次逐级比 较,直至找到下一个最小记录为止;反复此过程直 至序列有序。
五、希尔排序:
希尔排序(Shell’s method),又称为“缩小增 量排序”(diminishing increment sort),是一种比较 复杂的插入排序。
希尔排序的思想是:用一定的增量间隔将待排序 列分成多个组,每组都采用简单插入排序;排序完一 遍后,缩小增量间隔,再对新的分组采用简单插入排 序;反复此过程,直至增量间隔为 1 ,即整个待排序 列为一组时,执行一遍简单插入排序后结束。
二、折半插入排序:
折半插入排序(binary insertion sort)与直接插入 排序不同之处在于查找插入位置时不是用顺序查找, 而是用折半查找。
折半插入排序的移动次数与直接插入排序相同, 只是比较次数少了,因此其时间复杂度也为 O(n 2)。
三、2-路插入排序:
2-路插入排序目的是为了减少排序过程中移动 记录的次数,代价是需要 n 个记录的辅助空间 d : 将 r[1] 赋值给 d[1],将 d 看成循环的,其它记录均 与 d[1] 比较,比起小则在 d[1] 前插入,反之则在 d[1] 后插入。
ENDP;
排序性能分析:
比较次数: 最好情况 — n-1 最坏情况 — (n+2)(n-1)/2
平均比较次数: (n+4)(n-1)/4 移动次数: 最好情况 — 2(n-1) 最坏情况 — (n+4)(n-1)/2
平均移动次数: (n+8)(n-1)/4
可见,直接插入排序的时间复杂度为 O(n 2)。但 在待排序列有序的的情况下,直接插入排序的时间复 杂度下降为 O(n)。
不稳定的排序方法(unstable sorting method)
待排序列中存在两个或以上关键字相等的记录, 设Ki=Kj (1≤i < j≤n),即排序前 Ri 在 Rj 前,若在排序 后 Rj 却在 Ri前,则称排序是不稳定稳定的。
内部排序(internal sorting)
待排序列记录全部存放在计算机随机存储器中进 行排序的过程称为内部排序。
增量为 3 :12215 8 9797 32 12 29194 12215 452 324154 256 618 37475 增量为 1 : 21 8 77 32 12 99 125 452 214 256 618 345 排序结果 : 8 12 21 32 77 99 125 214 256 345 452 618
方法:将相邻两记录一一比较,将关键字较小的记录 交换在前面,反复此过程,直到待排序列有序为止。
PROC bubblesort (VAR r : list); For i := 1 To n - 1 Do For j := 1 To n - i Do If r [ j ].key > r [ j + 1 ].key Then r [ j ] ←→ r [ j + 1 ]
§10.1 插入排序
一、直接插入排序: 直接插入排序(straight insertion sort)是一种
最简单的排序方法:将记录一个个插入到已排序好 的有序表中,从而得到长度增加的新的有序表。
PROC straightsort (VAR r : list); For i := 2 To n Do straightsortpass ( r , i )
ENDP;
起泡排序也是一种稳定的排序,时间复杂度为 O ( n 2 ) 。
二、快速排序:
快速排序(quick sort)是对起泡排序的改进:将 待排序列第一个元素——枢轴元素(pivot)放置到序 列中的某个位置,使其前面的所有元素的关键字都小 于它,后面的所有元素的关键字都大于它;再分别对 枢轴元素前面和后面的两段待排序列采用快速排序方 法,直至每一段都只剩下一个元素为止。
第十章. 内部排序 (Chapter 10. Internal Sorting)
排序(sorting)
排序又称分类,是计算机中最重要的操作,它是 将一个数据元素(或记录)的任意序列排列成一个按 关键字有序的序列。
稳定的排序方法(stable sorting method)
若待排序列中存在两个或以上关键字相等的记 录,设Ki=Kj (1≤i < j≤n),即排序前 Ri 在 Rj 前,若在 排序后 Ri 仍在 Rj 前,则称排序是稳定的。
在空间复杂度上,除静态数据外,由于递归的原因, 栈的最大深度在最好的情况下为 O( log n ) ,在最坏的 情况下为 n 。每次都先对较短的子序列先进行排序能降 低栈的深度。
快速排序是不稳定排序。
作
业
29. 试证明:当待排序列已呈现出有 序状态时,快速排序的时间复杂度为 O ( n 2 )。
30. 试以单链表为存储结构实现简单 插入排序。
ENDP;
希尔排序的时间复杂度与增量序列有关,分析起来 很复杂,有人认为为 O ( n 1.5 ),也有人认为为 O ( n 1.3 )。
在以上插入排序中,除希尔排序为不稳定排序外, 其余的都是稳定的排序。
§10.2 交换排序
一、起泡排序: 起泡排序( bubble sort )也是一种最简单的排序
ENDP; PROC simpleselectionsort (VAR r : list );
For i := 1 To n Do simpleselectionpass ( r , i ) ENDP;
简单选择排序是稳定的排序,其时间复杂度为 O( n 2 )。
二、树形选择排序:
借鉴体育比赛中淘汰赛的做法,将两两必赛过 的优胜者推举出去与其它组的优胜者比赛,反复此 过程,直到决出冠军为止;若能记住每次比赛的结 果,则亚军的产生不必再经过此过程,只需将与冠 军赛过的每一个运动员逐级进行比赛,即可得到亚 军,这就是树形选择排序的思路。
外部排序(external sorting)
待排序列记录数量太大,不能全部存放在计算机 随机存储器中,排序过程中需对计算机外存进行访问, 这种排序过程称为外部排序。
排序过程中的两种基本操作:
1、比较操作:比较两个关键字值的大小的操作。
2、移动操作:将记录从一个位置移动到另一个位 置的操作。
待排序列的三种存储结构:
第六次上机作业
输入若干组长度各异的待排序列, 分别用快速排序算法和改进的枢轴元 素三者取中算法对待排序列进行排序, 当待排子序列长度已小于 20时,改用 直接插入排序,利用时间函数验证三 者取中算法在效率上的提高。(提示: 待排序列的长度一般应为 5000 以上)
§10.3 选择排序
一、简单选择排序: 简单选择排序(simple selection sort)同样也是
PROC quickpass (VAR r : list; s , t : integer; VAR i : integer); i := s; j := t; rp := r [ s ]; x := t [ s ].key; While i < j Do 【 While (i < j) And (r[ j ].key ≥ x) Do j := j -1; r [ i ] :=r [ j]; While (i < j) And (r[ j ].key ≤ x) Do i := i +1; r [ j ] :=r [ i ] 】; r [ i 】;
PROC Shellsort (VAR r : Array[-d[1]..n] Of rectype; d:Array[1..t] Of integer); k := 1; While k ≤ t Do Begin Shellpass ( d [ k ] ); k := k + 1 End
2-路插入排序的移动次数大约为 n 2 / 2,因此其 时间复杂度仍为 O(n 2)。
四、表插入排序:
表插入排序需附设一个指针域,通过改变指针的 值来达到不移动记录而得到排序结果的目的。
表插入排序是用改变指针来代替移动记录操作, 因此其时间复杂度还为 O(n 2)。
表插入排序的结果是形成了链表,因此查找时只 能用顺序查找,为能使用折半查找,需对记录重新排 序,但这不影响其时间复杂度。
一种最简单的排序方法:每次从待排序列中选出关键 字最小记录作为有序序列中最后一个记录,直至最后 一个记录为止。
PROC simpleselectionpass (VAR r : list; i : integer); k := i; For j := i + 1 To n Do If r [ j ] .key < r [ k ].key Then k := j; If k ≠ i Then r [ i ] ←→ r [ k ]
ENDP;
快速排序是基于比较和交换的排序方法里最快 的一种排序,其时间复杂度为 O( n log n )。
但快速排序的效率不太稳定,在关键字均匀分 布时,效率最高;在关键字有序时,效率将退化为 O ( n 2 ) 。如何解决这个难题呢?
其实,我们仔细分析就可看出,效率低是因为枢轴 元素的选取有问题:我们希望每次选取的枢轴元素都处 于待排序列中间位置,但当待排序列有序时,枢轴元素 的取值每次都是最大的或最小的。有鉴于此,我们能否 考虑在枢轴元素选取时,与部分元素比较一下,选取它 们中处于中间大小的元素与枢轴元素交换,作为新的枢 轴元素,通常是将处于待排序列头部、尾部和中间的三 个元素比较,从而得到新的枢轴元素,这种方法叫“三 者取中法”,它能很有效的防止快速排序效率的退化。