第10章-内部排序PPT课件
合集下载
第10章 排序 PPT课件
清华大学出版社
概述
数据结构(C++版)
排序算法的存储结构
从操作角度看,排序是线性结构的一种操作,待排序 记录可以用顺序存储结构或链接存储结构存储。
假定1:采用顺序存储结构,关键码为整型,且记录 只有关键码一个数据项。
int r[n+1]; //待排序记录存储在r[1]~r[n],r[0]留做他用
假定2:将待排序的记录序列排序为升序序列。
i = 6 18 10 15 21 25 25* 18
10 15 18 21 25 25*
r[0]的作用? 暂存单元 43;+版)
关键问题(1)如何构造初始的有序序列?
解决方法:
将第1个记录看成是初始有序表,然后从第2个记录起 依次插入到这个有序表中,直到将第n个记录插入。 算法描述:
学号 0001 0002 0003 …
姓名 王军 李明 汤晓影
…
高数 85 64 85 …
英语 68 72 78 …
思想品德 88 92 86 …
清华大学出版社
概述
数据结构(C++版)
排序的基本概念
单键排序:根据一个关键码进行的排序; 多键排序:根据多个关键码进行的排序。
学号 0001 0002 0003 …
算法描述:
r[0]=r[i]; j=i-1; while (r[0]<r[j]) {
r[j+1]=r[j]; j--; }
r[0]有两个作用:
1. 进入循环之前暂存了r[i] 的值,使得不致于因记录 的后移而丢失r[i]的内容;
2. 在查找插入位置的循环 中充当哨兵。
清华大学出版社
插入排序
姓名 王军 李明 汤晓影
第10章内部排序[1]PPT课件
13
8.2 交换排序
冒泡排序
排序过程
将第一个记录的关键字与第二个记录的关键字进行 比较,若为逆序r[1].key>r[2].key,则交换;然 后比较第二个记录与第三个记录;依次类推,直至 第n-1个记录和第n个记录比较为止——第一趟冒 泡排序,结果关键字最大的记录被安置在最后一个 记录上 对前n-1个记录进行第二趟冒泡排序,结果使关键 字次大的记录被安置在第n-1个记录位置 重复上述过程,直到“在一趟排序过程中没有进行 过交换记录的操作”为止
7
折半插入排序 排序过程:用折半查找方法确定插入位置的排序叫~
例 i=1
(30) 13 70 85 39 42 6 20
i=2 13 (13 30) 70 85 39 42 6 20
…...
i=7 6 (6 i=8 20 (6
s i=8 20 (6
s i=8 20 (6
i=8 20 (6
i=8 20 (6
时间复杂度:T(n)=O(n²) 空间复杂度:S(n)=O(1)
9
希尔排序(缩小增量法) 排序过程:先取一个正整数d1<n, 把所有相隔d1的记录放一组,组内 进行直接插入排序;然后取d2<d1, 重复上述分组和排序操作;直至 di=1,即所有记录放进一个组中排 序为止
10
例 初始: 49 38 65 97 76 13 27 48 55 4 取d1=5 一趟分组:49 38 65 97 76 13 27 48 55 4
13 30 39 42 70 85 ) 20
13 30 39 m
13 30 39 mj 13 30 39
s mj
42 70 42 70 42 70
85 ) 20 j 85 ) 20
8.2 交换排序
冒泡排序
排序过程
将第一个记录的关键字与第二个记录的关键字进行 比较,若为逆序r[1].key>r[2].key,则交换;然 后比较第二个记录与第三个记录;依次类推,直至 第n-1个记录和第n个记录比较为止——第一趟冒 泡排序,结果关键字最大的记录被安置在最后一个 记录上 对前n-1个记录进行第二趟冒泡排序,结果使关键 字次大的记录被安置在第n-1个记录位置 重复上述过程,直到“在一趟排序过程中没有进行 过交换记录的操作”为止
7
折半插入排序 排序过程:用折半查找方法确定插入位置的排序叫~
例 i=1
(30) 13 70 85 39 42 6 20
i=2 13 (13 30) 70 85 39 42 6 20
…...
i=7 6 (6 i=8 20 (6
s i=8 20 (6
s i=8 20 (6
i=8 20 (6
i=8 20 (6
时间复杂度:T(n)=O(n²) 空间复杂度:S(n)=O(1)
9
希尔排序(缩小增量法) 排序过程:先取一个正整数d1<n, 把所有相隔d1的记录放一组,组内 进行直接插入排序;然后取d2<d1, 重复上述分组和排序操作;直至 di=1,即所有记录放进一个组中排 序为止
10
例 初始: 49 38 65 97 76 13 27 48 55 4 取d1=5 一趟分组:49 38 65 97 76 13 27 48 55 4
13 30 39 42 70 85 ) 20
13 30 39 m
13 30 39 mj 13 30 39
s mj
42 70 42 70 42 70
85 ) 20 j 85 ) 20
数据结构课件_第10章 内部排序
4.什么叫内部排序和外部排序?
内部排序—待排序记录都在内存中 外部排序—待排序记录一部分在内存,一部分在外存
5.排序的分类?
交换排序、插入排序、选择排序、归并排序、基数排序
6.待排序记录数据类型的定义
#define MAXSIZE 1000 // 待排顺序表最大长度 typedef int KeyType; // 关键字类型为整数类型
象移动次数约为 n2/4。因此,直接插入排序
的时间复杂度为 o(n2)。
•直接插入排序是一种稳定的排序方法。
2) 折半插入排序
新元素插入到哪里? 在已形成的有序表中折半查找,并在适 当位置插入,把原来位置上的元素向后顺移。 插入位置 hight+1 i 例如: L.r 14 36 49 52 80 58 61 23 97 75
是否可以考虑 设计一个“黄 金分割”插入 算法
// 折半
if (L.r[0].key < L.r[m].key)
high = m-1; // 插入点在低半区
else low = m+1; // 插入点在高半区
}
3)希尔(shell)排序(又称缩小增量排序)
基本思想:先将整个待排记录序列分割成若干子序列,分 别进行直接插入排序,待整个序列中的记录“基本有序” 时,再对全体记录进行一次直接插入排序。 技巧:子序列的构成不是简单地“逐段分割”,而是将 相隔某个增量dk的记录组成一个子序列,让增量dk逐趟缩
{张三,男,16} 、 {赵六,女,17} 、{王五,男,17}、{李四,女,18}
R3 R2
不稳 定
大多数排序算法都有两个基本的操作: (1)比较两个关键字的大小
(2)将记录从一个位置移动到另一个位置
西安电子科技大学_数据结构_第十章内部排序_课件PPT
初始关键字序列:
12345678 49 38 65 97 76 13 27 49*
第一趟排序后:
38 49 65 76 13 27 49* 97
第二趟排序后:
38 49 65 13 27 49* 76 97
第三趟排序后:
38 49 13 27 49* 65 76 97
第四趟排序后:
38 13 27 49 49* 65 76 97
10.2 希尔排序算法
void ShellInsert(SqList &L,int dk) {//对顺序表L作一+i 1<i=<L=.eLn.getnhg;tih+;+i+) +)
iiff((LL..rr[[ii]]..kkeeyy<<LL..rr[[ii--d1k]]..kkeeyy)){{//需将L.r[i]插入有序增量子表
10.1 排序的基本概念(续)
正序与逆序
➢ 若有序表是按排序码升序排列的,则称为升序表或正序 表,否则称为降序表或逆序表。不失普遍性,我们一般 只讨论正序表。
排序方法度量
➢ 排序过程主要是比较记录的关键字和移动记录。因此排 序的时间复杂性可以算法执行中的数据比较次数及数据 移动次数来衡量。当一种排序方法使排序过程在最坏或 平均情况下所进行的比较和移动次数越少,则认为该方 法的时间复杂性就越好。
L.r[j+1] = L.r[j];
L.r[j+1] = L.r[0]; }//if
最好情况} 下// (I正ns序er)tSort
最坏情况下(逆序)
元素的❖ 比分较析次直数接为插: 入n 排- 1序算法中关键元字素的的比比较较次次数数和: 记(录n+移2动)(次n-数1)/2
第10章 内部排序 资料水利水电学院.ppt
一、 直接插入排序 (Straight Insertion Sort)
基本思想是:假设待排序的记录存放在数组R[1..n]中。初始 时,R[1]自成1个有序区,无序区为R[2..n]。从i=2起直至i=n为止, 依次将R[i]插入当前的有序区R[1..i-1]中,生成含n个记录的有序 区。
当插入第i (i 1) 个记录时,前面的 R[1], …, R[i-1]已经排好 序。这时,用R[i]的关键字与R[i-1], R[i-2], … R[1] 的关键字顺序 进行比较,找到插入位置即将R[i]插入,插入位置之后的所有记 录依次向后移动。
InfoType otherinfo; //其它数据项
}RcdType;
typedef struct {
RcdType r[MAXSIZE+1]; // r[0] 闲置或用作哨兵单元
int length;
//顺序表长度
}SqList;
//顺序表类型
9
2. 评价排序算法好坏的标准: ① 时间性能分析 以算法中用得最多的基本操作的执行次数(或者其 数量级)来衡量,这些操作主要是比较元素、移动或 交换元素。在一些情况下,可能还要用这些次数的平 均数来表示。
13
直接插人排序算法描述: 方法:Ki与Ki-1,Ki-2,…K1依次比较,直到找到应插入的位置。 void InsertSort (SqList&L){ //对顺序表L作直接插入排序。
for(i=2;i<=L.length;++i) if LT(L.r[i].key,L.r[i-1].key){//“<”,需将L.r[i]插入有序子表 L.r[0]=L.r[i] //复制为哨兵 L. r[i] = L. r[i-1]; //后移 for ( j=i-2 ; LT(L.r[0].key,L.r[j].key); --j) L.r[j+1]=L.r[j]; //记录后移 L.r[j+1]=L.r[0] // 插入到正确位置 }
基本思想是:假设待排序的记录存放在数组R[1..n]中。初始 时,R[1]自成1个有序区,无序区为R[2..n]。从i=2起直至i=n为止, 依次将R[i]插入当前的有序区R[1..i-1]中,生成含n个记录的有序 区。
当插入第i (i 1) 个记录时,前面的 R[1], …, R[i-1]已经排好 序。这时,用R[i]的关键字与R[i-1], R[i-2], … R[1] 的关键字顺序 进行比较,找到插入位置即将R[i]插入,插入位置之后的所有记 录依次向后移动。
InfoType otherinfo; //其它数据项
}RcdType;
typedef struct {
RcdType r[MAXSIZE+1]; // r[0] 闲置或用作哨兵单元
int length;
//顺序表长度
}SqList;
//顺序表类型
9
2. 评价排序算法好坏的标准: ① 时间性能分析 以算法中用得最多的基本操作的执行次数(或者其 数量级)来衡量,这些操作主要是比较元素、移动或 交换元素。在一些情况下,可能还要用这些次数的平 均数来表示。
13
直接插人排序算法描述: 方法:Ki与Ki-1,Ki-2,…K1依次比较,直到找到应插入的位置。 void InsertSort (SqList&L){ //对顺序表L作直接插入排序。
for(i=2;i<=L.length;++i) if LT(L.r[i].key,L.r[i-1].key){//“<”,需将L.r[i]插入有序子表 L.r[0]=L.r[i] //复制为哨兵 L. r[i] = L. r[i-1]; //后移 for ( j=i-2 ; LT(L.r[0].key,L.r[j].key); --j) L.r[j+1]=L.r[j]; //记录后移 L.r[j+1]=L.r[0] // 插入到正确位置 }
数据结构课件第10章_内排序
按排序过程中使用到的存储介质来分,可以将排 序分成两大类 内排序和外排序。 序分成两大类:内排序和外排序。 两大类: 内排序是指在排序过程中所有数据均放在内存中 内排序是指在排序过程中所有数据均放在内存中 处理,不需要使用外存的排序方法。而对于数据量很 大的文件,在内存不足的情况下,则还需要使用外存, 这种排序方法称为外排序 这种排序方法称为外排序。 外排序。 排序码相同的记录,若经过排序后,这些记录 仍保持原来的相对次序不变,称这个排序算法是稳 仍保持原来的相对次序不变,称这个排序算法是稳 不稳定的排序算法。 定的。否则,称为不稳定的排序算法 定的。否则,称为不稳定的排序算法。
为了方便, 为了方便,r[0]一般不用 一般不用 于存放排序码, 于存放排序码,在一些排序 /*此处还可以定义记录中除排序码外的其它域* /*此处还可以定义记录中除排序码外的其它域*/ 算法中它可以用来作为中间 }recordtype; }recordtype; /*记录类型的定义*/ /*记录类型的定义* 单元存放临时数据。 单元存放临时数据。length 域是待排序的记录个数, 域是待排序的记录个数,它 typedef struct{ 必须不大于MAXSIZE,这样, 必须不大于 ,这样, recordtype r[MAXSIZE+1]; r[MAXSIZE+1 第1~length个记录的排序码 个记录的排序码 int length; length; /*待排序文件中记录的个数*/ /*待排序文件中记录的个数* 分别存于 r[1].key~r[length].key中 中 }table; /*待排序文件类型* /*待排序文件类型*/
最坏情况 : 即初始排序码开始是逆序的情况下,因为当插入 第i个排序码时,该算法内循环while要执行i次条件判 个排序码时,该算法内循环while要执行i 断,循环体要执行i 次,每次要移动1 断,循环体要执行i-l次,每次要移动1个记录,外循 环共执行n 环共执行n-1次,其循环体内不含内循环每次循环要 进行2 进行2次移动操作,所以在最坏情况下,比较次数为 (1+2+…+n)*(n-1),移动次数为 (1+2+…+n)*(n-1),移动次数为 (1+2+2+2+…+n+2)*(n-1)。假设待排序文件中的记录 (1+2+2+2+…+n+2)*(n-1)。假设待排序文件中的记录 以各种排列出现的概率相同,因为当插入第i 以各种排列出现的概率相同,因为当插入第i个排序码 时,该算法内循环while平均约要执行i/2次条件判断, 时,该算法内循环while平均约要执行i/2次条件判断, 循环体要执行(i 循环体要执行(i-l)/2次,外循环共执行n-1次,所以 /2次,外循环共执行n 平均比较次数约为(2+3+…+n)/2*(n-1),平均移动次 平均比较次数约为(2+3+…+n)/2*(n-1),平均移动次 数为(n-1)*(2+1+3+1+…+n+1)/2,也即直接插入排序 数为(n-1)*(2+1+3+1+…+n+1)/2,也即直接插入排序 算法的时间复杂度为O(n 算法的时间复杂度为O(n2)。
第十章 内部排序
共进行n-1趟排序, 共进行n(n-1)/2次比较 T(n)=O(n2)
二、快速排序
• 算法思想:
1. 指定枢轴(通常为第一个记录)
2. 通过一趟排序将以枢轴为中心,把待排记录 分割为独立的两部分,使得左边记录的关键 字小于枢轴值,右边记录的关键字大于枢轴 值
3. 对左右两部分记录序列重复上述过程,依次 类推,直到子序列中只剩下一个记录或不含 记录为止。
27 38 13 49 76 97 65 49 13 27 38 49 65 76 97
具体实现: low=s; high=t; pivotkey=L.r[low].key; 1. 从high开始往前找第一个关键字小于pivotkey的记 录,与枢轴记录交换 2. 从 low 开始往后找第一个关键字大于 pivotkey 的记 录,与枢轴记录交换 3. 重复上述两步直到low= =high为止 4. 此时枢轴记录所在的位置i=low=high
int partition(SqList &L, int low, int high) { //交换顺序表L中的子表L.r[low..high]的记录,枢轴记录到位,并返回其所在位置 //此时在它之前(后)的记录均不大(小)于它 piovtkey=L.r[low].key; //用子表的第一个记录作枢轴记录 while(low<high) //从表的两端交替地向中间扫描 { while(low<high&&L.r[high].key>=piovtkey) - -high; L.r[low] L.r[high]; //将比枢轴记录小的记录交换到低端 while(low<high&&L.r[low].key<=priotkey) ++low; L.r[low] L.r[high]; //将比枢轴记录大的记录交换到高端 } return low; //返回枢轴所在的位置 }//Partition
内部排序
7
2013-8-3
第十章 内部排序
直接插入排序算法
void insertsort (sqlist r, int n) { int i,j; for( i=2; i<=n; i++) { r[0]=r[i]; /* r[0]用于暂时存放待插入的元素*/ j= i-1; /* j为待比较元素下标,初始时指 向待插入元素前一个单元*/
起来叫做排序(sort)。
对一批记录的排序,应该指定是根据记录中哪
个域的数据进行排列。这个作为排序依据的数 据域我们称之为关键字(key)。
本章讨论的排序均为按递增顺序排序,并假定
要排序的记录均已存储在一个一维数组中。
2013-8-3 第十章 内部排序 2
该一维数组定义如下:
#define MAXITEM 100 struct record { KeyType key; /*关键字*/ ElemType data; /*其他域*/ }sqlist[MAXITEM];
2013-8-3 第十章 内部排序 8
直接插入排序算法续
while (r[0].key<r[j].key) { r[j+1]=r[j]; j--; } r[j+1]=r[0]; /* 在j+1位置插入r[0]*/ }
}
简单插入排序的时间复杂性是O(n2)(平均约为n2 /4)。 对于有相同关键字记录的情况,此算法是稳定的。
2013-8-3 第十章 内部排序 6
(0)
42 [20 [17 [13 [13 [13 [13 [13
20 42] 20 17 17 14 14 14
17
13
28
14
23
2013-8-3
第十章 内部排序
直接插入排序算法
void insertsort (sqlist r, int n) { int i,j; for( i=2; i<=n; i++) { r[0]=r[i]; /* r[0]用于暂时存放待插入的元素*/ j= i-1; /* j为待比较元素下标,初始时指 向待插入元素前一个单元*/
起来叫做排序(sort)。
对一批记录的排序,应该指定是根据记录中哪
个域的数据进行排列。这个作为排序依据的数 据域我们称之为关键字(key)。
本章讨论的排序均为按递增顺序排序,并假定
要排序的记录均已存储在一个一维数组中。
2013-8-3 第十章 内部排序 2
该一维数组定义如下:
#define MAXITEM 100 struct record { KeyType key; /*关键字*/ ElemType data; /*其他域*/ }sqlist[MAXITEM];
2013-8-3 第十章 内部排序 8
直接插入排序算法续
while (r[0].key<r[j].key) { r[j+1]=r[j]; j--; } r[j+1]=r[0]; /* 在j+1位置插入r[0]*/ }
}
简单插入排序的时间复杂性是O(n2)(平均约为n2 /4)。 对于有相同关键字记录的情况,此算法是稳定的。
2013-8-3 第十章 内部排序 6
(0)
42 [20 [17 [13 [13 [13 [13 [13
20 42] 20 17 17 14 14 14
17
13
28
14
23
数据结构ppt 第10章 内部排序
量,在排序过程中将指针内容逐个修改为已经整理(排序)
过的后继记录地址。 优点:在排序过程中不移动元素,只修改指针。 本方法具有链表排序和地址排序的特点。
链表排序——排序时只移动指针; 地址排序——排序时先移动地址,最后再移动记录。
13
10.2 插入排序---表插入排序
例:关键字序列 T=(21,25,49,25*,16,08), 请写出表插入排序的具体实现过程。 *表示后一个25 解:假设该序列(结构类型)已存入一维数组V[7]中,将V[0] 作为表头结点。则算法执行过程为: i 关键字 V[i].key 指针 V[i].link MaxNum 5 6 0 1 2 0 1 21 4 3 2 25 0
97
final 76 76 76 65 97
38
first 38
final
97 final 97 final 76 97 final 13 first 13 first 27 13 first 27
first
38 38 38
10.2 插入排序---表插入排序
基本思想:在顺序存储结构中,给每个记录增开排序
冒泡排序的算法分析 时间效率:O(n2) — 因为要考虑最坏情况 空间效率:O(1)— 只在交换时用到一个缓冲单元 稳 定 性:稳定 — 25和25*在排序前后的次序未改变 详细分析: • 最好情况:初始排列已经有序,只执行一趟起泡,做 n-1 次关键码比较,不移动对象。 • 最坏情形:初始排列逆序,算法要执行n-1趟起泡,第i趟 (1 i n) 做了n- i 次关键码比较,执行了n-i 次对象交换。 此时的比较总次数KCN和记录移动次数RMN为:
3
10.2 插入排序---希尔(shell)排序(又称缩小增量排序) 基本思想:先将整个待排记录序列分割成若干子序列,分别
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
L.r[j+1]=L.r[j]; //将j……i-1的记录后移一格 L.r[j+1]=L.r[0]; } //将Ri插入到位置j+1 }
-
算法效率
时间复杂度
待排序记录按关键字从小到大排列(正序)
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-路归并排序 基数排序
-
3. 排序的基本操作
LMH
H LM H+1:插入位置
i=2: (65) (38 49) 65 97 76 13 27 49
LM H;1:插入位置
i=8:
(13 27 38 49 49 65 76 97)
-
算法程序
void BInsertSort ( Sqlist &L)
{ for( i=2; i<=L.length; ++i ) {
}RedType;
//关键字项 //其它数据项 //记录类型
type struct {
RedType r[MAXSIZE+1]; //r[0]空作为哨兵
int length;
//顺序表长度
}SqList;
//顺序表类型
-
5. 算法复杂度分析
评价排序算法的标准:
执行时间 所需辅助空间 稳定性
实现排序时修改地址向量中的地址,排序结束时统一 调整记录的存储位置
-
顺序存储结构定义
#define MAXSIZE 20 //顺序表的长度 typedef int KeyType; //关键字类型为整数类型
typedef struct{ KeyType key; InfoType otherinfo;
-
算法程序
viod Dinsertsort(Sqlist &L) { for (i=2;i<=L.length;++i) //对每一个Ri∈R
//小于时,需将L.r[i]插入到有序表 if LT(L.r[i].key, L.r[i-1].key) { L.r[0]=L.r[i]; //复制为哨兵
/*寻找插入位置j*/ for (j=i-1; LT(L.r[0].key, L.r[j].key); --j)
排序的稳定性:假设Ki=Kj,(1≤i≤n; 1≤j≤n; i≠j)且在排序前的序列中Ri领先于Rj,如在排序后 Ri仍领先于Rj,则称所用的排序方法是稳定的,反 之则称排序方法是不稳定的。
-
2. 排序的分类
待排序记录所在位置
内部排序:待排序记录存放在内存中 外部排序:排序过程中需对外存进行访问的排序
排序的基本操作:
比较操作:比较两个关键字的大小 改变指向记录的指针(逻辑关系)或将一个记录从
一个位置移动到另一个位置
-
4. 数据的存储形式
待排记录一般有三种存储形式
存放在一组地址连续的存储单元中,类似顺序表
实现排序必须借助移动记录
存放在静态链表中
实现排序只需修改指针
存放在一组地址连续的存储单元中,同时另设一 个指示各个记录存储位置的地址向量
R’={R1} R={ R2,R3,……,Rn }
若R[1..i-1]为有序区,寻找R[i]插入位置的方法:
在R[0]处设置监视哨,即令:R[0]=R[i] 从j=i-1的记录位置开始依次向前比较 若R[i].key<R[j].key,R[j]后移,否则插入位置找到
,将R[i]插入到第j+1个位置
第10章 内部排序
主要内容: 排序的基本概念 插入排序 交换排序 选择排序 归并排序 各种排序方法的比较
-
§10.1 概述
1. 基本概念
排序:将一个数据元素(或记录)的任意序列,重新 排列成一个按关键字有序的序列的过程叫排序。
设序列{R1, R2, …, Rn},相应关键字序列为{ K1, K2, …, Kn },所谓排序是指重新排列{ R1, R2, …, Rn }为 { Rp1, Rp2, …, Rpn },使得满足: {Kp1≤Kp2 …… ≤Kpn} 或 {Kp1≥Kp2 ……≥Kpn}
非就地排序所要求的辅助空间一般为O(n)
-
§10.2 插入排序
1. 插入排序的基本思想
基本思想:设R={R1,R2,……,Rn}为原始序列 ,R’={ }初始为空。插入排序就是依次取出R中的
元素Ri,然后将Ri有序地插入到R’中。
例如:
有序插入
R={5,2,10,2}
R’={ }
R={2,10,2}
L.r[0]=L.r[i];
low=1; high=i-1;
while (low<=high){ //折半查找位置
m=(low+high)/2;
if (L.r[0].key<L.r[m].key) high=m-1;
排序算法的时间开销
排序所需时间
简单排序:T(n)=O(n2) 先进的排序:T(n)=O(logn) 基数排序:T(n)=O(d.n)
主要是关键字的比较次数和记录的移动次数。
有的排序算法其执行时间不仅依赖于问题的规模,还取 决于输入实例中数据的状态。
排序算法的空间开销
若所需辅助空间不依赖于问题的规模n,即辅助空间为 O(1),则称为就地排序。
-
算法效率
时间复杂度
待排序记录按关键字从小到大排列(正序)
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-路归并排序 基数排序
-
3. 排序的基本操作
LMH
H LM H+1:插入位置
i=2: (65) (38 49) 65 97 76 13 27 49
LM H;1:插入位置
i=8:
(13 27 38 49 49 65 76 97)
-
算法程序
void BInsertSort ( Sqlist &L)
{ for( i=2; i<=L.length; ++i ) {
}RedType;
//关键字项 //其它数据项 //记录类型
type struct {
RedType r[MAXSIZE+1]; //r[0]空作为哨兵
int length;
//顺序表长度
}SqList;
//顺序表类型
-
5. 算法复杂度分析
评价排序算法的标准:
执行时间 所需辅助空间 稳定性
实现排序时修改地址向量中的地址,排序结束时统一 调整记录的存储位置
-
顺序存储结构定义
#define MAXSIZE 20 //顺序表的长度 typedef int KeyType; //关键字类型为整数类型
typedef struct{ KeyType key; InfoType otherinfo;
-
算法程序
viod Dinsertsort(Sqlist &L) { for (i=2;i<=L.length;++i) //对每一个Ri∈R
//小于时,需将L.r[i]插入到有序表 if LT(L.r[i].key, L.r[i-1].key) { L.r[0]=L.r[i]; //复制为哨兵
/*寻找插入位置j*/ for (j=i-1; LT(L.r[0].key, L.r[j].key); --j)
排序的稳定性:假设Ki=Kj,(1≤i≤n; 1≤j≤n; i≠j)且在排序前的序列中Ri领先于Rj,如在排序后 Ri仍领先于Rj,则称所用的排序方法是稳定的,反 之则称排序方法是不稳定的。
-
2. 排序的分类
待排序记录所在位置
内部排序:待排序记录存放在内存中 外部排序:排序过程中需对外存进行访问的排序
排序的基本操作:
比较操作:比较两个关键字的大小 改变指向记录的指针(逻辑关系)或将一个记录从
一个位置移动到另一个位置
-
4. 数据的存储形式
待排记录一般有三种存储形式
存放在一组地址连续的存储单元中,类似顺序表
实现排序必须借助移动记录
存放在静态链表中
实现排序只需修改指针
存放在一组地址连续的存储单元中,同时另设一 个指示各个记录存储位置的地址向量
R’={R1} R={ R2,R3,……,Rn }
若R[1..i-1]为有序区,寻找R[i]插入位置的方法:
在R[0]处设置监视哨,即令:R[0]=R[i] 从j=i-1的记录位置开始依次向前比较 若R[i].key<R[j].key,R[j]后移,否则插入位置找到
,将R[i]插入到第j+1个位置
第10章 内部排序
主要内容: 排序的基本概念 插入排序 交换排序 选择排序 归并排序 各种排序方法的比较
-
§10.1 概述
1. 基本概念
排序:将一个数据元素(或记录)的任意序列,重新 排列成一个按关键字有序的序列的过程叫排序。
设序列{R1, R2, …, Rn},相应关键字序列为{ K1, K2, …, Kn },所谓排序是指重新排列{ R1, R2, …, Rn }为 { Rp1, Rp2, …, Rpn },使得满足: {Kp1≤Kp2 …… ≤Kpn} 或 {Kp1≥Kp2 ……≥Kpn}
非就地排序所要求的辅助空间一般为O(n)
-
§10.2 插入排序
1. 插入排序的基本思想
基本思想:设R={R1,R2,……,Rn}为原始序列 ,R’={ }初始为空。插入排序就是依次取出R中的
元素Ri,然后将Ri有序地插入到R’中。
例如:
有序插入
R={5,2,10,2}
R’={ }
R={2,10,2}
L.r[0]=L.r[i];
low=1; high=i-1;
while (low<=high){ //折半查找位置
m=(low+high)/2;
if (L.r[0].key<L.r[m].key) high=m-1;
排序算法的时间开销
排序所需时间
简单排序:T(n)=O(n2) 先进的排序:T(n)=O(logn) 基数排序:T(n)=O(d.n)
主要是关键字的比较次数和记录的移动次数。
有的排序算法其执行时间不仅依赖于问题的规模,还取 决于输入实例中数据的状态。
排序算法的空间开销
若所需辅助空间不依赖于问题的规模n,即辅助空间为 O(1),则称为就地排序。