数据结构、排序(插入排序、选择排序、冒泡排序和快速排序)

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

二、排序的稳定性
当待排序记录的关键字均不相同时,排序结果是 惟一的,否则排序结果不唯一。 在待排序的文件中,若存在多个关键字相同的记
录,经过排序后这些具有相同关键字的记录之间的相
对次序保持不变,该排序方法是稳定的;若具有相同 关键字的记录之间的相对次序发生变化,则称这种排
序方法是不稳定的。
注意:
排序算法的稳定性是针对所有输入实例而言的。
数来表示比较运算。 【例】关键字为字符串时,可定义宏“#define LT(a,
b)(Stromp((a),(b))<0)”。那么算法中“a<b”可用“LT(a, b)”取代。若使用C++,则定义重载的算符“<”更为方便。
8. 2 插入排序
插入排序(Insertion Sort)的基本思想是:每次将一 个待排序的记录,按其关键字大小插入到前面已经排 好序的子文件中的适当位置,直到全部记录插入完成 为止。
即在所有可能的输入实例中,只要有一个实例使得算 法不满足稳定性要求,则该排序算法就是不稳定的。
例: 初始关键字:49,38,65,97,76,13,27,49’ 排序结果: 13,27,38,49,49’,65,76,97 稳定的 13,27,38, 49’ , 49,65,76,97 不稳定的
三、排序方法的分类
{ 在 R[1..i-1]中查找R[i]的插入位臵;
插入R[i] ;
}
例如
0
1
2
3
4
5
6
7
8
49 38 65 97 76 13 27 52 j j=i-1 插入位臵 插入38
0 1 2 3 4 5 6 7 8
38 49 65 97 76 13 27 52 j=i-1
0 1 2 3 4
插入65
5 6
一趟直接插入排序的基本思想:
有序序列R[1..i-1] R[i] 无序序列 R[i..n]
有序序列R[1..i]
无序序列 R[i+1..n]
实现“一趟插入排序”可分三步进行:
1.在R[1..i-1]中查找R[i]的插入位臵,
R[1..j].key R[i].key < R[j+1..i-1].key;
这些关键字相互之间可以进行比较,即在
它们之间存在着这样一个关系 : Kp1≤Kp2≤…≤Kpn
按此固有关系将上式记录序列重新排列为 { Rp1, Rp2, …,Rpn } 的操作称作排序。
1.被排序对象--文件 被排序的对象——文件由一组记录组成。 记录则由若干个数据项(或域)组成。其中有一项可 用来标识一个记录,称为关键字项。该数据项的值称
1. 插入排序
将无序子序列中的一个或几
个记录“插入”到有序序列中,
从而增加记录的有序子序列的长 度。
2. 交换排序
通过“交换”无序序列中的记
录从而得到其中关键字最小或最大 的记录,并将它加入到有序子序列
中,以此方法增加记录的有序子序
列的长度。
3. 选择排序
从记录的无序子序列中“选择”
关键字最小或最大的记录,并将它 加入到有序子序列中,以此方法增
typedef int KeyType; //假设的关键字类型
typedef struct{ //记录类型
KeyType key; //关键字项 InfoType otherinfo;//其它数据项,类型InfoType依赖
于具体应用而定义 }RecType; typedef RecType SeqList[n+1];//SeqList为顺序表类型, 表中第0个单元一般用作哨兵 注意: 若关键字类型没有比较算符,则可事先定义宏或函
从R[i-1]起向前进行顺序查找, 监视哨设臵在R[0];
R[0] R[i]
j R[0] = R[i];
j=i-1 插入位臵
// 设臵“哨兵” // 从后往前找
for (j=i-1; R[0].key<R[j].key; --j); 循环结束表明R[i]的插入位臵为 j +1
对于在查找过程中找到的那些关键 字不小于R[i].key的记录,并在查找的
第8章 排 序
排序和查找是计算机科学中十分重要的一类问题,因为就总 体而言,计算机的运行时间中有相当大的一部分是用于处理此 任务的。因此,在有的关于数据结构的论述中,将排序和查找 归结为计算机程序设计中的两项常用技术。 本章介绍排序,重点介绍依据插入思想的直接插入排序和希尔 排序;依据交换思想的冒泡排序和快速排序;依据选择思想的 直接选择排序和堆排序;依据合并思想的归并排序;以及依据 分配思想的基数排序等。要求熟悉各种排序算法的基本思想、 排序过程和时间、空间的性能分析,了解各种排序算法的特点 与使用的情况。 重点提示:★掌握各种排序方法的排序过程、时空效率、稳定 性和适用情况。 ★一些排序算法的实现(如插入排序、选择排序、冒泡排序和 快速排序)。 ★堆的概念和建立。
方式。
2.待排文件的常用存储方式 (1) 以顺序表(或直接用向量)作为存储结构 排序过程:对记录本身进行物理重排(即通过关键字之 间的比较判定,将记录移到合适的位置) (2) 以链表作为存储结构 排序过程:无须移动记录,仅需修改指针。通常将这 类排序称为链表(或链式)排序; (3) 用顺序的方式存储待排序的记录,但同时建立一个 辅助表(如包括关键字和指向记录位置的指针组成的索引表) 排序过程:只需对辅助表的表目进行物理重排(即只 移动辅助表的表目,而不移动记录本身)。适用于难于在 链表上实现,仍需避免排序过程中移动记录的排序方法。
同时实现记录向后移动;
for (j=i-1; R[0].key<R[j].key; --j); R[j+1] = R[j]
R[0] R[i]
j
j= i-1 插入位臵
上述循环结束后可以直接进行“插入”
令 i = 2,3,…, n, 实现整个序列的排序。 for ( i=2; i<=n; ++i )
if (R[i].key<R[i-1].key)
加记录的有序子序列的长度。
4. 归并排序
通过“归并”两个或两个以上的 记录有序子序列,逐步增加记录有
序序列的长度。
5. 分配排序
借助多关键字排序的思想对单逻 辑关键字进行排序的方法。
四、排序算法分析
1.排序算法的基本操作
大多数排序算法都有两个基Baidu Nhomakorabea的操作:
(1) 比较两个关键字的大小; (2) 改变指向记录的指针或移动记录本身。 注意: 第(2)种基本操作的实现依赖于待排序记录的存储
2.将R[j+1..i-1]中的所有记录均后移
一个位臵;
3.将R[i] 插入(复制)到R[j+1]的位臵上。
不同的具体实现方法导致不同的算法描述
直接插入排序(基于顺序查找)
希尔排序(基于逐趟缩小增量)
8.2.1 直接插入排序
利用 “顺序查找”实现
“在R[1..i-1]中查找R[i]的插入位臵”
算法的实现要点:
7
8
12 27 38 49 65 76 97 52 j=i-1 插入52 j
插入位臵
6 7 0 1 2 3 4 5 8
12 27 38 49 52 65 76 97

i=1
(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 i=7 27 (13 27 49 65 65 76 97 38 38 49 76 97) 27
3.排序算法性能评价 (1) 评价排序算法好坏的标准 评价排序算法好坏的标准主要有两条: ① 执行时间和所需的辅助空间 ② 算法本身的复杂程度 (2) 排序算法的空间复杂度 若排序算法所需的辅助空间并不依赖于问题的规模n, 即辅助空间是O(1),则称之为就地排序(In-Place Sort)。 非就地排序一般要求的辅助空间为O(n)。 (3) 排序算法的时间开销 大多数排序算法的时间开销主要是关键字之间的比较 和记录的移动。有的排序算法其执行时间不仅依赖于问题 的规模,还取决于输入实例中数据的状态。
例如:将下列关键字序列 52, 49, 80, 36, 14, 58, 61, 23, 97, 75
调整为
14, 23, 36, 49, 52, 58, 61 ,75, 80, 97
一般情况下, 假设含n个记录的序列为{ R1, R2, …, Rn }
其相应的关键字序列为 { K1, K2, …,Kn }
全部记录放入内存的大文件。
2.按排序依据原则划分
内部排序的过程是一个逐步扩大
记录的有序序列长度的过程。 有序序列区 无 序 序 列 区 ki
有序序列区
经过一趟排序
无 序 序 列 区
基于不同的“扩大” 有序序列长
度的方法,内部排序方法大致可分 下列几种类型:
插入排序
交换排序
选择排序 归并排序
分配排序
2.哨兵的作用 算法中引进的附加记录R[0]称监视哨或哨兵 (Sentinel)。 哨兵有两个作用: ① 进入查找(插入位置)循环之前,它保存了R[i]的 副本,使不致于因记录后移而丢失R[i]的内容; ② 它的主要作用是:在查找循环中"监视"下标变 量j是否越界。一旦越界(即j=0),因为R[0].key和自己 比较,循环判定条件不成立使得查找循环结束,从而 避免了在该循环内的每一次均要检测j是否越界(即省略 了循环判定条件"j>=1")。
8.1 基本概念
8.2 插入排序
8.3 交换排序
8.4 选择排序
8.5 归并排序
8.6 分配排序 8.7 各种内部排序方法的比较和选择
8.1 基本概念
一、排序的定义
二、排序的稳定性
三、排序方法的分类 四、排序算法分析 五、文件的顺序存储结构表示
一、什么是排序?
所谓排序,就是要整理文件中的记
录,使之按关键字递增(或递减)次序排列 起来。
五、文件的顺序存储结构表示
在本章中,若无特别申明,均假定是按关键字递
增序排序,且以顺序表作为文件的存储结构。为简单
起见,假设关键字类型为整型。但因为除关键字外可 能还有其他数据域,且排序不会改变表长,故将第2章 的顺序表类型说明修改为:
#define n l00 //假设的文件长度,即待排序的记录数目
注意: ① 实际上,一切为简化边界条件而引入的附加结点 (元素)均可称为哨兵。 【例】单链表中的头结点实际上是一个哨兵 ② 引入哨兵后使得测试查找循环条件的时间大约 减少了一半,所以对于记录数较大的文件节约的时间 就相当可观。对于类似于排序这样使用频率非常高的 算法,要尽可能地减少其运行时间。所以不能把上述 算法中的哨兵视为雕虫小技,而应该深刻理解并掌握 这种技巧。
j j j j j j 排序结果:(13 27 38 49 65 76 97)
void lnsertSort(SeqList R) { //对顺序表R中的记录R[1..n]按递增序进行插入排序 int i,j; for(i=2;i<=n;i++) //依次插入R[2],…,R[n] if(R[i].key<R[i-1].key){//若R[i].key大于等于有序区 //中所有的keys,则R[i]应在原有位置上 R[0]=R[i];j=i-1; //R[0]是哨兵,且是R[i]的副本 do{ //从右向左在有序区R[1..i-1]中查找R[i]的// 插入位置 R[j+1]=R[j]; //将关键字大于R[i].key的记录后移 j-- ; }while(R[0].key<R[j].key); //当R[i].key≥R[j].key 时终止 R[j+1]=R[0]; //R[i]插入到正确的位置上 }//endif }//InsertSort
为关键字(Key)。
注意: 在不易产生混淆时,将关键字项简称为关键字。
2.排序运算的依据--关键字 用来作排序运算依据的关键字,可以是数字类型, 也可以是字符类型。 关键字的选取应根据问题的要求而定。
【例】在高考成绩统计中将每个考生作为一个记录。
每条记录包含准考证号、姓名、各科的分数和总分数 等项内容。若要惟一地标识一个考生的记录,则必须 用"准考证号"作为关键字。若要按照考生的总分数排 名次,则需用"总分数"作为关键字。
1.按是否涉及数据的内、外存交换划分 在排序过程中,若整个文件都是放在内存中处理, 排序时不涉及数据的内、外存交换,则称之为内部排
序(简称内排序);反之,若排序过程中要进行数据的内、
外存交换,则称之为外部排序。 注意:
① 内排序适用于记录个数不很多的小文件
② 外排序则适用于记录个数太多,不能一次将其
相关文档
最新文档