chap009-排序
合集下载
数据结构chapter 9 排序.ppt

MAXINT 49 38 65 97 76 13 27 49
2
310 - - - - -
i=4
MAXINT 49 38 65 97 76 13 27 49
2
3140 - - - -
21-Jan-20
23
重新排列算法
表插入排序方法结束后,各个节点的next指针域给出 了下一个元素的位置,它们形成一个有序链表
q=7
MAXINT 13 27 65 97 76 49 38 52
6
(6) (7) 5 0 4 8 1 3
MAXINT 13 27 38 97 76 49 65 52
6
(6) (7) (7) 0 4 8 5 3
MAXINT 13 27 38 49 76 97 65 52
6
(6) (7) (7) (6) 4 0 5 3
r1?对于后面的每个元素首先与d1的值比较如果比d1的值小则插入到d1前面有序表中否则插入到d1后面有序表中?在插入过程可以采用折半查找来确定插入的位置?需要将辅助空间看成是一个循环空间并设两个指针first和final来记录得到的有序序列在d中的位置?由于这种方法将一个有序表当作两个有序表来处理因此称为2路排序22oct12202路排序示例final4938659776132749初始序列辅助空间状态49firstfinal4938firstii2i3ifinal496538first22oct1221表插入排序?无论是直接插入排序折半排序还是2路排序均需要移动元素?要想在排序过程中不移动元素需要改变数据的存储结构比如用链表结构通过修改指针来实现?表插入排序就是通过修改节点中的指针域来实现排序而不需要移动元素的?节点结构c描述
由于这种方法将一个有序表当作两个有序表来处理, 因此称为2-路排序
数据结构chap2顺序表

#define LISTINCREMENT 10 // 线性表存储空间的分配增量
typedef struct { ElemType *elem; // 存储空间基址 int length; // 当前长度 int listsize; // 当前分配的存储容量 // (以sizeof(ElemType)为单位)
99070104 单晓宏
男
81.3
......
......
......
......
......
......
数据元素都是记录; 元素间关系是线性 同一线性表中的元素必定具有相同特性
00:57
抽象数据类型线性表的定义为:
ADT List { 数据对象: D={ ai | ai ∈ElemSet, i=1,2,...,n, n≥0 } {称 n 为线性表的表长; 称 n=0 时的线性表为空表。}
数据关系: R1={ <ai-1 ,ai >|ai-1 ,ai∈D, i=2,...,n }
{设线性表为 (a1,a2, . . . ,ai,. . . ,an), 称 i 为 ai 在线性表中的位序。}
00:57
线性表的基本操作
1. 初始化线性表L InitList(L) 2. 销毁线性表L DestoryList(L) 3. 清空线性表L ClearList(L) 4. 求线性表L的长度 ListLength(L) 5. 判断线性表L是否为空 IsEmpty(L) 6. 获取线性表L中的某个数据元素内容 GetElem(L,i,e) 7. 检索值为e的数据元素 LocateELem(L,e) 8. 在线性表L中插入一个数据元素 ListInsert(L,i,e) 9. 删除线性表L中第i个数据元素 ListDelete(L,i,e)
typedef struct { ElemType *elem; // 存储空间基址 int length; // 当前长度 int listsize; // 当前分配的存储容量 // (以sizeof(ElemType)为单位)
99070104 单晓宏
男
81.3
......
......
......
......
......
......
数据元素都是记录; 元素间关系是线性 同一线性表中的元素必定具有相同特性
00:57
抽象数据类型线性表的定义为:
ADT List { 数据对象: D={ ai | ai ∈ElemSet, i=1,2,...,n, n≥0 } {称 n 为线性表的表长; 称 n=0 时的线性表为空表。}
数据关系: R1={ <ai-1 ,ai >|ai-1 ,ai∈D, i=2,...,n }
{设线性表为 (a1,a2, . . . ,ai,. . . ,an), 称 i 为 ai 在线性表中的位序。}
00:57
线性表的基本操作
1. 初始化线性表L InitList(L) 2. 销毁线性表L DestoryList(L) 3. 清空线性表L ClearList(L) 4. 求线性表L的长度 ListLength(L) 5. 判断线性表L是否为空 IsEmpty(L) 6. 获取线性表L中的某个数据元素内容 GetElem(L,i,e) 7. 检索值为e的数据元素 LocateELem(L,e) 8. 在线性表L中插入一个数据元素 ListInsert(L,i,e) 9. 删除线性表L中第i个数据元素 ListDelete(L,i,e)
数据机构Chap10-内部排序

65
97
76
13
27
49
(49 65 76 97)
final
(38)
first (13 first (13 first 97 final 13 27 38) 27 38) 38)
i=6:
(49
65
76
97) final
i=7:
(49
65
76
97) final
i=8:
(49
49
65
76
first
算法性能分析:
1 2 n
即使序列成为一个按关键字有序的序列 Rp Rp Rp
1 2
n
这样的一种操作称为排序。
上述排序中的关键字可以是主关键字,也可以是次 关键字,如果是主关键字,则排序结果是唯一的; 若是次关键字,排序结果可能不是唯一的。 假设Ki=Kj(1<=i,j<=n,ij),且在排序前的序列中 Ri领先于Rj(即i<j),若在排序后的序列中Ri仍领先 于Rj,则称所用的排序方法是稳定的,否则是不稳 定的。 根据排序过程中涉及的存储器不同,排序分为内部 排序和外部排序两类:内部排序指待排记录存放在 计算机内存中。外部排序由于待排记录数量大,存 放在外存中,排序时需要不断在内外存交换数据。
一般情况下,第i趟直接插入排序的操作为: 在含有i-1个记录的有序子序列r[1..i-1]中插 入一个记录r[i]后,变成含有i个记录的有序 子序列r[1..i];并且,和顺序查找类似,为 了在查找插入位置的过程中避免数组下标 出界,在r[0]处设置监视哨。在自i-1起往前 搜索的过程中,可以同时后移记录。 整个排序过程为进行n-1趟插入,即:先将 序列中的第1个记录看成是一个有序的子序 列,然后从第2个记录起逐个进行插入,直 至整个序列变成按关键字非递减有序序列 为止。
chap_10 排序

二趟排序: 二趟排序: 13 4 48 38 27 49 55 65 97 76 取d3=1 13 三趟分组: 三趟分组: 4 48 38 27 49 55 65 97 76
三趟排序: 三趟排序: 13 27 38 48 49 55 65 76 97 4
8
希尔排序特点
子序列的构成不是简单的“逐段分割” 子序列的构成不是简单的“逐段分割”,而是将 相隔某个增量的记录组成一个子序列 希尔排序可提高排序速度, 希尔排序可提高排序速度,因为
2
3.排序的数据类型描述 排序的数据类型描述 在以后讨论排序时,待排序记录的数据类型统一描述如下 待排序记录的数据类型统一描述如下: 在以后讨论排序时 待排序记录的数据类型统一描述如下 typedef struct{ #define MAXSIZE 20 //r[0]闲置或用作哨兵单元 闲置或用作哨兵单元 typedef int KeyType; RedType R[MAXSIZE+1]; typedef struct{ int length; //顺序表长度 顺序表长度 KeyType key; //关键字项 关键字项 }SqList; InfoType otherinfo; //其它数据项 其它数据项 } RedType; 10.2 插入排序 一.直接插入排序 直接插入排序 基本思想:把一个记录插入到已排好序的有序表中 从而得到 基本思想 把一个记录插入到已排好序的有序表中,从而得到 把一个记录插入到已排好序的有序表中 一个新的记录数增1 一个新的记录数增 的有序表
6
希尔排序(缩小增量法 希尔排序 缩小增量法) 缩小增量法
排序过程:先取一个正整数 排序过程:先取一个正整数d1<n,把 , 所有相隔d1的记录放一组, 所有相隔 的记录放一组,组内进行直接插 的记录放一组 入排序;然后取 入排序;然后取d2<d1,重复上述分组和 , 排序操作;直至di=1, 排序操作;直至di=1,即所有记录放进一 个组中排序为止
chap2数据结构,顺序表,树,图,链表,排序

2.4 一元多项式的表示
ADT List { 数据对象: D={ ai | ai ∈ElemSet, i=1,2,...,n, n≥0 } { 称 n 为线性表的表长; 称 n=0 时的线性表为空表。} 数据关系:
R1={ <ai-1 ,ai >|ai-1 ,ai∈D, i=2,...,n }
{ 设线性表为 (a1,a2, . . . ,ai,. . . ,an), 称 i 为 ai 在线性表中的位序。}
i = 1; found = TRUE; while ( i<= La_len && found ) {
GetElem(LA, i, e); // 取得LA中一个元素
if (LocateElem(LB, e, equal( ))
i++;
// 依次处理下一个
else found = FALSE;
// LB中没有和该元素相同的元素
{加工型操作} ClearList( &L ) ( 线性表置空 ) PutElem( &L, i, &e ) ( 改变数据元素的值 ) ListInsert( &L, i, e ) ( 插入数据元素 ) ListDelete( &L, i, &e ) ( 删除数据元素 )
ClearList( &L ) 初始条件:线性表 L 已存在。 操作结果:将 L 重置为空表。 PutElem( &L, i, e ) 初始条件: 线性表 L 已存在, 且 1≤i≤LengthList(L)。 操作结果:L 中第 i 个元素赋值和 e 相同。
线性结构的基本特征: 线性结构 是 一个数据元素的有序(次序)集 1.集合中必存在唯一的一个“第一元素” 2.集合中必存在唯一的一个 “最后元素”
chap4-2-排序

排 (3) 关键字较小旳统计跳跃式前移,在进行最终一趟增量为1 序 旳插入排序时,序列已基本有序。
15
4.2.2 插入排序—— 直接插入、折半插入、希尔排序
3、希尔排序
效率分析 希尔排序时效分析极难,关键字旳比较次数与统计移动次
第 数依赖于步长因子序列旳选用,特定情况下能够精确估算出关
二 键字旳比较次数和统计旳移动次数。
第 二 i=4
(38 49 65 97) 76 13 27 for(i=2;i<=p->length;i++)
if(p->r[i].key < p->r[i-1].key)
节 i=5 76 (38 49 65 76 97) 13 27 { p->r[0].key=p->r[i].key;//设置监测
第四章 查找与排序
第 2 节 排序
一、概 述 二、插入排序 三、互换排序 四、选择排序 五、小结
1
4.2 排 序
4.2.1 概 述
1、排序旳功能:将一种数据元素(或统计)旳任意序列,重
新排成一种按关键字有序旳序列。
第 二 节
2、排序过程旳构成环节: • 首先比较两个关键字旳大小; • 然后将统计从一种位置移动到另一种位置。
节
p->elem[j+dk]=p->elem[0]; //插入到正确位置
}
排}
序 void ShellInsert (STBL *p,int dlta[],int t)
{ //按增量序列dlta[0,1…,t-1]对顺序表*p作希尔排序
for(k=0;k<t;t++) //一共执行 t 次调用插入排序
Chaper10_排序
排序算法的效率分析
与许多算法一样,对各种排序算法性能的评价主要从 两个方面来考虑,一是时间性能;二是空间性能。 1. 时间复杂度分析
排序算法的时间复杂度可用排序过程 中记录之间关键字的比较次数与记录的移
动次数来衡量。
2.空间复杂度分析
排序算法的空间复杂度是指算法在执行时所需的附加存 储空间,也就是用来临时存储数据的内存使用情况。
即使得式(8-1)的序列成为一个按关键字有序的序列
{R
p1,R p2
,…,Rpn}
(8-3)
这个将原有表中任意顺序的记录变成一个按关键字有 序排列的过程称为排序。
2.排序分类 增排序和减排序:
如果排序的结果是按关键字从小到大的 次序排列的,就是增排序,否则就是减 排序。
稳定排序和不稳定排序 内部排序与外部排序:
待排序的顺序表类型的类型定义如下: typedef int KeyType //定义关键字类型 typedef struct dataType { keytype key; //记录类型 //关键字项
elemtype otherelement;
}RecType;
//其他数据项
10.2 插入排序
插入排序的基本思想是:每次将一个待排序的记录,
堆排序方法:是由J. Williams和Floyd提出的一种改进 方法,它在选择当前最小关键字记录的同时,还保存了 本次排序过程所产生的比较信息。
不断从待排记录序列中选出关键字最小的记录插入已排
序记录序列的后面,直到n个记录全部插入已排序记录 序列中。 主要介绍两种选择排序方法: 简单选择排序
堆排序。
10.4 选择排序
10.4.1 简单选择排序 简单选择排序(Simple Selection Sort)也称直接选择 排序,是选择排序中最简单直观的一种方法。 其基本操作思想: (1)每次从待排记录序列中选出关键字最小的记录; (2)将它与待排记录序列第一位置的记录交换后,再将 其“插入”已排序记录序列(初始为空);
数据结构chap8排序
30 30 76
27 7267 9370
7163 927 6350
9173 6257 380
13 1439 27 3183 4297 30 1635 3287 4390
字
键
例
数 据 结 构
序
排
章
八
第
❖算法描述
数
据 void bubble_sort(NODE r[ ],int n)
结 构
{
int i,j;
i (n 2)(n 1) n2
i2 2
4
4
排
记录移动次数: n2
4
序
空间复杂度:S(n)=O(1)
稳定的
折半插入排序
数
❖排序过程:用折半查找方法确定插入位置的排序叫~
据 结
例
i=1
(30) 13 70 85 39 42 6 20
构
i=2 13 (13 30) 70 85 39 42 6 20
…..
NODE x;
for(i=2;i<=n;i++)
{ for(j=n ; j>=i ; j--)
{ if(r[j].key<r[j-1].key)
{ x=r[j];
r[j]=r[j-1];
第
r[j-1]=x;
八
}
章
}
}
}
排
序
void bubble_sort(NODE r[],int n) { int m,i,j; , flag =1;
数
❖基本思想
据 结 构
通过一趟排序,将待排序记录分割成独立的两部分, 其中一部分记录的关键字均比另一部分记录的关键字
数据结构-排序PPT课件
平均情况时间复杂度
O(nlogn),归并排序的平均时间复杂度为O(nlogn)。其中,n为待排序序列的长度。
06
基数排序
基数排序是一种非比较型整数排序算法,其原理是将整数按位数切割成不同的数字,然后按每个位数分别比较。
分配和收集
基数排序是一种稳定的排序算法,即相同的元素在排序后仍保持原有的顺序。
文件系统需要对文件和目录进行排序,以便用户可以更方便地浏览和管理文件。
数据挖掘和分析中需要对数据进行排序,以便发现数据中的模式和趋势。
计算机图形学中需要对图形数据进行排序,以便进行高效的渲染和操作。
数据库系统
文件系统
数据挖掘和分析
计算机图形学
02
插入排序
将待排序的元素按其排序码的大小,逐个插入到已经排好序的有序序列中,直到所有元素插入完毕。
简单选择排序
基本思想:将待排序序列构造成一个大顶堆,此时,整个序列的最大值就是堆顶的根节点。将其与末尾元素进行交换,此时末尾就为最大值。然后将剩余n-1个元素重新构造成一个堆,这样会得到n个元素的次小值。如此反复执行,便能得到一个有序序列了。 时间复杂度:堆排序的时间复杂度为O(nlogn),其中n为待排序元素的个数。 稳定性:堆排序是不稳定的排序算法。 优点:堆排序在最坏的情况下也能保证时间复杂度为O(nlogn),并且其空间复杂度为O(1),是一种效率较高的排序算法。
基数排序的实现过程
空间复杂度
基数排序的空间复杂度为O(n+k),其中n为待排序数组的长度,k为计数数组的长度。
时间复杂度
基数排序的时间复杂度为O(d(n+k)),其中d为最大位数,n为待排序数组的长度,k为计数数组的长度。
适用场景
当待排序数组的元素位数较少且范围较小时,基数排序具有较高的效率。然而,当元素位数较多或范围较大时,基数排序可能不是最优选择。
O(nlogn),归并排序的平均时间复杂度为O(nlogn)。其中,n为待排序序列的长度。
06
基数排序
基数排序是一种非比较型整数排序算法,其原理是将整数按位数切割成不同的数字,然后按每个位数分别比较。
分配和收集
基数排序是一种稳定的排序算法,即相同的元素在排序后仍保持原有的顺序。
文件系统需要对文件和目录进行排序,以便用户可以更方便地浏览和管理文件。
数据挖掘和分析中需要对数据进行排序,以便发现数据中的模式和趋势。
计算机图形学中需要对图形数据进行排序,以便进行高效的渲染和操作。
数据库系统
文件系统
数据挖掘和分析
计算机图形学
02
插入排序
将待排序的元素按其排序码的大小,逐个插入到已经排好序的有序序列中,直到所有元素插入完毕。
简单选择排序
基本思想:将待排序序列构造成一个大顶堆,此时,整个序列的最大值就是堆顶的根节点。将其与末尾元素进行交换,此时末尾就为最大值。然后将剩余n-1个元素重新构造成一个堆,这样会得到n个元素的次小值。如此反复执行,便能得到一个有序序列了。 时间复杂度:堆排序的时间复杂度为O(nlogn),其中n为待排序元素的个数。 稳定性:堆排序是不稳定的排序算法。 优点:堆排序在最坏的情况下也能保证时间复杂度为O(nlogn),并且其空间复杂度为O(1),是一种效率较高的排序算法。
基数排序的实现过程
空间复杂度
基数排序的空间复杂度为O(n+k),其中n为待排序数组的长度,k为计数数组的长度。
时间复杂度
基数排序的时间复杂度为O(d(n+k)),其中d为最大位数,n为待排序数组的长度,k为计数数组的长度。
适用场景
当待排序数组的元素位数较少且范围较小时,基数排序具有较高的效率。然而,当元素位数较多或范围较大时,基数排序可能不是最优选择。
数据结构Chap10 内部排序.ppt
85 ) 20 h 85 ) 20
85 ) 20
85 ) 20
13 20 30 39 42 70 85 )
算法描述
void BInsertSort (SqList &L)
{ // 对顺序表L作折半插入排序
for ( i=2; i<=L.length; ++i )
{ L.r[0] = L.r[i];
——少
排序过程中所需的辅助空间的大小 ——小
算法本身的复杂程度
10.2 插入排序
插入排序的准则:在有序序列中插入新的记录以 达到扩大有序区的长度的目的。 直接插入排序
排序过程:整个排序过程为n-1趟插入,即先 将序列中第1个记录看成是一个有序子序列, 然后从第2个记录开始,逐个进行插入,直至 整个序列有序。
增量序列取法
无除1以外的公因子 采用缩小增量法 最后一个增量值必须为1
11.3 交换排序
基本思想:两两比较待排序记录的关键字,发现 两个记录的次序相反时即进行交换,直到没有反序 的记录为止。
两种交换排序: (1)冒泡排序 (2)快速排序
冒泡排序
最简单的一种交换排序方法 排序过程
将第一个记录的关键字与第二个记录的关键字进行比较, 若逆序则交换;然后比较第二个记录与第三个记录;依次类 推,直至第n-1个记录和第n个记录比较为止——第一趟冒泡 排序,结果关键字最大的记录被安置在最后一个记录上。
void ShellSort(RecType R[],int n) /*希尔排序算法*/
{ int i,j,d;RecType temp;
d=n/2;
/*d取初值n/2*/
while (d>0) {
for (i=d;i<n;i++) /*将R[d..n-1]分别插入各组当前有序区*/
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
二、折半插入排序
因为 R[1..i-1] 是一个按关键字有 序的有序序列,则可以利用折半查找 折半查找 实现“在R[1..i-1]中查找 查找R[i]的插入位 查找 置”,如此实现的插入排序为折半插 折半插 入排序。
void BiInsertionSort ( SqList &L ) { for ( i=2; i<=L.length; ++i ) { L.r[0] = L.r[i]; // 将 L.r[i] 暂存到 L.r[0] 中折半查找插入位置; 在 L.r[1..i-1]中折半查找插入位置; 中折半查找插入位置 for ( j=i-1; j>=high+1; --j ) L.r[j+1] = L.r[j]; // 记录后移 L.r[high+1] = L.r[0]; // 插入 } // for } // BInsertSort
有序序列区
无 序 序 列 区 经过一趟排序
有序序列区
无 序 序 列 区
基于不同的“扩大 有序序列长 扩大” 扩大 度的方法,内部排序方法 方法, 方法 内部排序方法大致可分 下列几种类型:
插入类 归并类
交换类
选择类
其它方法
#define MAXSIZE 1000 // 待排顺序表最大长度 待排记录的数据类型定义如下: 待排记录的数据类型定义如下 typedef int KeyType; // 关键字类型为整数类型 typedef struct { KeyType key; // 关键字项 InfoType otherinfo; // 其它数据项 } RcdType; // 记录类型 typedef struct { RcdType r[MAXSIZE+1]; // r[0]闲置 闲置 int length; // 顺序表长度 } SqList; // 顺序表类型
二、内部排序和外部排序
若整个排序过程不需要访问外存 不需要访问外存便 不需要访问外存 能完成,则称此类排序问题为内部排 内部排 序; 反之,若参加排序的记录数量很大, 整个序列的排序过程不可能在内存中 外部排序。 完成,则称此类排序问题为外部排序 外部排序
三、内部排序的方法
内部排序的过程是一个逐步扩大 逐步扩大 记录的有序序列长度 有序序列长度的过程。 有序序列长度
例如:将下列关键字序列 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 } 这些关键字相互之间可以进行比较,即在 它们之间存在着这样一个关系 : Kp1≤Kp2≤…≤Kpn ≤ 按此固有关系将上式记录序列重新排列为 { Rp1, Rp2, …,Rpn } 的操作 操作称作排序 排序。 操作 排序
排序前 ( 56, 34, 47, 23, 66, 18, 82, 47 ) 若排序后得到结果 ( 18, 23, 34, 47, 47, 56, 66, 82 ) 则称该排序方法是稳定的 则称该排序方法是稳定的 稳定 若排序后得到结果 ( 18, 23, 34, 47, 47, 56, 66, 82 ) 则称该排序方法是不稳定的 则称该排序方法是不稳定的 不稳定
对于有n个数 对于有 个数 据元素的待排 序列, 序列,插入操 作要进行n-1 作要进行 次
第五次排序: 第五次排序: [15 27 36 42 53 69]
直接插入排序示例
void InsertionSort ( SqList &L ) { // 对顺序表 L 作直接插入排序。
for ( i=2; i<=L.length; ++i ) if (L.r[i].key < L.r[i-1].key) { L.r[0] = L.r[i]; // 复制为监视哨 for ( j=i-1; 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 = n −1
i =2
n
0
最坏的情况(关键字在记录序列中逆序有序): 最坏的情况(关键字在记录序列中逆序有序):
“比较”的次数:
“移动”的次数:
(n + 2)(n −1) ∑(i) = 2 i =2
n
(n + 4)(n −1) ∑(i +1) = 2 i=2
n
直接插入排序是一种稳定的排序方法 初始序列的为正序时时间复杂度为: 初始序列的为正序时时间复杂度为: O(n), 初始序列的为逆序时时间复杂度 ( ), 为:O(n2) ( 不是每趟排序后都将某个数据放置在它 的最终位置
稳定的排序方法指的是, 稳定的排序方法指的是,对于 指的是 两个关键字相等的记录, 两个关键字相等的记录,它们在序 列中的相对位置, 列中的相对位置,在排序之前和排 序之后, 序之后,没有发生改变
排序之前 : { · · · · · Ri(K) · · · · · Rj(K) · · · · } 排序之后 : { · · · · · Ri(K) Rj(K) · · · · ·· · · · ·}
待排元素序列: 待排元素序列:[53] 27 36 15 69 42 第一次排序: 第一次排序: [27 53] 36 15 69 42 第二次排序: 第二次排序: [27 36 53] 15 69 42 第三次排序: 第三次排序: [15 27 36 53] 69 42 第四次排序: [15 27 36 第四次排序: 53 69] 42 该算法适合于n 该算法适合于 较 小的情况, 小的情况,时间复 杂度为O(n2) 杂度为
R[1..j].key ≤ R[i].key < R[j+1..i-1].key;
2.将R[j+1..i-1]中的所有记录均后移 .
一个位置;
3.将R[i] 插入(复制)到R[j+1]的位置上。 .
不同的具体实现方法导致不同的算法描述
基于顺序查找) 直接插入排序(基于顺序查找)
折半插入排序(基于折半查找) 基于折半查找)
基于链表存储) 表插入排序(基于链表存储)
பைடு நூலகம்
基于逐趟缩小增量) 希尔排序(基于逐趟缩小增量)
一、直接插入排序
利用 “顺序查找”实现 顺序查找” “在R[1..i-1]中查找R[i]的插入位置”
算法的实现要点: 算法的实现要点:
从R[i-1]起向前进行顺序查找, 监视哨设置在R[0];
R[0] R[i]
• 排序算法的稳定性 如果在对象序列 排序算法的稳定性: 中有两个对象r[i]和 , 中有两个对象 和r[j],它们的关键 码 k[i] == k[j],且在排序之前,对象 ,且在排序之前, r[i]排在 前面。如果在排序之后, r[i]排在r[j]前面。如果在排序之后, 排在r[j]前面 对象r[i]仍在对象 的前面, 仍在对象r[j]的前面 对象 仍在对象 的前面,则称这 个排序方法是稳定的, 个排序方法是稳定的,否则称这个排 序方法是不稳定的
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的记录,并在查找的 同时实现记录向后移动; for (j=i-1; R[0].key<R[j].key; --j); R[j+1] = R[j]
4. 归并类
通过“归并”两个或两个以上的 “归并” 记录有序子序列,逐步增加记录有 序序列的长度。
5. 其它方法
10. 2 插入排序
一趟直接插入排序的基本思想:
有序序列R[1..i-1] R[i] 无序序列 R[i..n]
有序序列R[1..i]
无序序列 R[i+1..n]
实现“一趟插入排序”可分三步进行: 实现“一趟插入排序”可分三步进行: 1.在R[1..i-1]中查找R[i]的插入位置, .
如何在排序之后调整记录序列? 如何在排序之后调整记录序列? 算法中使用了三个指针: 其中:p指示第i个记录的当前位置 i指示第i个记录应在的位置 q指示第i+1个记录的当前位置
void Arrange ( Elem SL[ ], int n ) { p = SL[0].next; // p指示第一个记录的当前位置 for ( i=1; i<n; ++i ) { while (p<i) p = SL[p].next; q = SL[p].next; // q指示尚未调整的表尾 if ( p!= i ) { SL[p]←→SL[i]; // 交换记录,使第 个记录到位 交换记录,使第i个记录到位 SL[i].next = p; // 指向被移走的记录 } p = q; // p指示尚未调整的表尾, // 为找第i+1个记录作准备 }
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) { 在 R[1..i-1]中查找R[i]的插入位置; 插入R[i] ; }
内部排序的时间分析 时间分析: 时间分析
实现内部排序的基本操作 基本操作有两个: 基本操作 (1)“比较”序列中两个关键字的 “比较” 大小; (2)“移动”记录。 “移动”