数据结构 第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++,附测试数据)

严蔚敏 数据结构第十章 内部排序的具体代码(c++,附测试数据)
int i = 1;
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

源代码--数据结构与算法(Python版)chap10 排序

源代码--数据结构与算法(Python版)chap10 排序
20
交换类
(2)快速排序 快速排序采用分而治之(Divide and Conquer)
的策略将问题分解成若干个较小的子问题,采用 相同的方法一一解决后,再将子问题的结果整合 成最终答案。快速排序的每一轮处理其实就是将 这一的基准数定位,直到所有的数都排序完成 为止。
21
快速排序的基本步骤:
1. 选定一个基准值(通常可选第一个元素); 2. 将比基准值小的数值移到基准值左边,形
14
• 交换类
交换类排序的基本思想是:通过交换无序序列 中的记录得到其中关键字最小或最大的记录,并将 其加入到有序子序列中,最终形成有序序列。交换 类排序可分为冒泡排序和快速排序等。
15
交换类
(1)冒泡排序 两两比较待排序记录的关键字,发现两
个记录的次序相反时即进行交换,直到没有 反序的记录为止。因为元素会经由交换慢慢 浮到序列顶端,故称之为冒泡排序。
3. 最后对这个组进行插入排序。步长的选法 一般为 d1 约为 n/2,d2 为 d1 /2, d3 为 d2/2 ,…, di = 1。
11
【例】给定序列(11,9,84,32,92,26,58,91,35, 27,46,28,75,29,37,12 ),步长设为d1 =5、d2 =3、 d3 =1,希尔排序过程如下:
for i in range(1,len(alist)):
#外循环n-1
for j in range(i,0,-1):
#内循环
if alist[j]<alist[j-1]:
alist[j],alist[j-1]=alist[j-1],alist[j] #交换
li=[59,12,77,64,72,69,46,89,31,9] print('before: ',li) insert_sort(li) print('after: ',li)

数据结构答案 第10章 排序学习与指导

数据结构答案 第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-严蔚敏)

第十章_排序方法(数据结构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)

北航数据结构课件 (10)

( 1,4,6 , 12 8,8 12 , 6,11,… )

49
temp
temp>K[j] j=0 38 97 76 65 13 27 50
… (若干趟后)
K[j+1]=K[ j ]; j=j−1;
65
38
49
76 65
76 97
65 97
13
27
50
K[j+1]=temp;
38
49
65
76
97
核心思想
首先确定一个元素的间隔数gap。 将参加排序的元素按照gap分隔成若干个子序列 ( 即分别把那些位置相隔为gap的元素看作一个子序 列),然后对各个子序列采用 某一种排序方法 进行排 序;此后减小gap值,重复上述过程,直到gap<1。
一种减小gap的方法:
gap1 = n/2 gapi = gapi-1/2
1.时间性能 —— 排序过程中元素之间的比较次数与元素的
移动次数。 本章讨论各种排序方法的时间复杂度 时主要按照最差情况下所需要的比较次数 来进行。
2.空间性能 —— 除了存放参加排序的元素之外,排序过程
中所需要的其他辅助空间。
3.排序稳定性 —— 对于值相同的两个元素,排序前后的先后
次序不变,则称该方法为稳定性排序方法, 否则,称为非稳定性排序方法。
算 法
泡排序法的排序趟数与原始序列中数 据元素的排列有关,因此,排序的趟数为 一个范围,即[1..n-1]。
什么情况下至少排序一趟 什么情况下要排序n-1趟
O(n
2)
结论
泡排序方法比较适合于 参加排序的序列的原始状态 基本有序的情况
泡排序法是 稳定性排序方法。

数据结构(严蔚敏)第10章

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

0
1
2
3ቤተ መጻሕፍቲ ባይዱ
4
5
6
7
j
算法要求A[n]=+∞,防止i超界。
程序10-4 快速排序 template <class T> void QSort(T A[],int left,int right) { int i,j; if ( left<right ) { i=left; j=right+1; do { do i++; while (A[i]<A[left]); do j--; while (A[j]>A[left]); if (i<j) Swap(A[i],A[j]); }while (i<j); Swap(A[left],A[j]); QSort(A,left,j-1); QSort(A,j+1,right); }//endif 继续 }
10.2.2 直接插入排序
基本思想:将序列中第1个元素作为一个有序序列,然 后将剩下的n-1个元素按关键字大小依次插入该有序序列, 经过n-1趟排序后即成为有序序列。
temp = 36 68 12 72 36 12
i
i之前是有序区;排序开 始的时候i=1;
48 36 68 72 12 48 02
A' A B
template <class T> void QuickSort(T A[],int n) { A[n]=maxnum; QSort(A,0,n-1); } 从上述快速排序算法中可以看出,经过每一趟排序后
,若被分割成两个大小相近的子序列时,快速排序的效
率最好,时间复杂度为O(nlog2n);反之,若每次分割的 两个子序列中有一个为空,即初始序列有序(顺序或逆序 ),则效率最低,时间复杂度为O(n2)。 快速排序是不稳定的排序方法。
i 48 left 36 68 72 12 48
j
02 ∞ right
找到小于A[left] 接下来会分别把 交换以后,只要 i 和 j 准 的元素(02), 尚未相遇,就 A[left]元素两侧 此时,i和j已经“相遇”过,扫描结束 继续各自的扫描以及交换操作; 备和A[i]交换; 的序列作为排序对 ,下面要把A[left]和A[j]交换,实现 和right“指针”指出了 其目的是把较A[left]小的元素放到 象递归整个算法过 了各元素按“左边小右边大”的原则 左边,较A[left]大的元素放到右边; 待排序的元素序列; 程;(过程略) 分布在A[left]两侧;
程序 10-1 简单选择排序 template <class T> void SelectSort(T A[], int n) { int small; for (int i=0; i<n-1; i++ ) // n-1趟 { small=i; for (int j=i+1; j<n; j++) if (A[j]<A[small]) small=j; Swap(A[i],A[small]); } //endfor } //函数Swap(T &a, T &b)交换两个元素 时间复杂度按比较次数衡量为O(n2)。
10.2.1 简单选择排序
基本思想:第1趟在初始序列(A[0]A[n-1])中找一 个最小值,与序列中第一个元素A[0]交换,这样子序列 (A[0])有序。 下一趟排序在子序列(A[1]A[n-1])中进行。
第i趟排序在子序列(A[i-1]A[n-1])中找最小值元
素与子序列中的第一个元素A[i-1]交换。经过n-1趟排 序后使得初始序列有序。
10.3 快速排序
基本思想:对任意给定的序列中元素Rs(关键字为Ks), 经过一趟排序后,将原序列分割成两个子序列,其中,前一 个子序列中的所有元素的关键字均小于等于Ks,后一个子序
列中元素的关键字均大于等于Ks。
称元素Rs 为分割元素。 以后只需对2个子序列分别进行快速排序,直到子序列
为空或只有一个元素时得到有序序列。
第一趟 排序;
48
36
j1
68
72
j2
12
48
02
i1
i2
size=2
36
48
68
72
12
Temp
48
02
此时的状态,适 第三趟排序;过程同前 合展示排序的 第二趟 (略);每一趟size以2倍增加,当 先按从小到大的顺 细节,请注意! 排序;
为避免发生最坏情况,选择分割元素时可作三种处理: (1)将A[(left+right)/2]作为分割元素,与A[left]交换; (2)选left到right间的随机整数k,将A[k]与A[left]交换; (3)取A[left]、A[(left+right)/2]和A[right]之中间值与 A[left]交换。 对于快速排序: (1)为提高快速排序的效率,将递归程序改为非递归的; (2)为减小栈空间,先对较小的子序列排序,将较大的子 序列进栈;
10.4 两路合并排序
基本思想:将有n个元素的序列看成是n个长度为1 的有序子序列,然后两两合并子序列,得到n/2个长度 为2或1的有序子序列;再两两合并,…,直到得到一个 长度为n的有序序列时结束。
3
j1 i1
j2 i2
此时i1+size<n的 条件已经不满足, 第一趟扫描结束;
size=1
temp中存放新的欲处 j 理元素; j是扫描 “指针”; 向前寻找插入的位置 ;
程序 10-2 直接插入排序 template <class T> void InsertSort(T A[], int n) { for(int i=1; i<n; i++ ) { int j=i; T temp=A[i]; while(j>0 && temp<A[j-1]) { A[j]=A[j-1]; j--; } A[j]=temp; } }
的次序排列为:
( Rp(0),Rp(1),…,Rp(n-1))
序列中两个元素Ri和 Rj (i<j),且 Ki=Kj,排 序后,Ri 仍然排在 Rj 之前,则称所用的排序算 法是稳定的。反之,称该排序算法是不稳定的。 3,1,3=>1,3,3 3,1,3=>1,3,3 如果待排序元素总数相对于内存而言较小,整 个排序过程可以在内存中进行,则称之为内部排序 ;反之,如果待排序元素总数较多,不能全部放入 内存,排序过程中需访问外存,则称之为外部排序 。 本章讨论内部排序。 本章采用顺序存储方式,即用一个一维数组 A[n+1](n为序列中元素个数)存储序列中各元素的 关键字,忽略元素的其它部分,把精力集中在排序 算法上。
0 1 2 3 4 5 6
(48, 36,68,72,12,48,02) (02),(36,68,72,12,48,48)
i指向无序区 的开始位置
i
small变量用来记录无序 区中最小元素的索引值;
small= 0 6 14
48 02
36
j
68
72
12
48
02 48
整个无序序列的 最小值02被放到i 位置后,第一遍扫 j为扫描“指针 描结束,进入第二 ”; 遍扫描;
该算法必须进行n-1趟,每趟进行n-i-1次比较,这样 总的比较次数为
n( n 1) ( n i 1) i 0 2
n 2
时间复杂度按比较次数衡量为O(n2)。另外,还需移
动元素3(n-1)次或交换元素(n-1)次。简单选择排序是
不稳定的排序方法。 关于稳定性问题: 3,1,3进行简单选择排序: 1,3,3 3,3,1进行简单选择排序: 1,3,3 1,3,3 (似乎是稳定的) 1,3,3
冒泡排序最好情况(已有序)下只需进行一趟排序,n-1 次比较,因此最好情况下的时间复杂度是O(n)。 最坏进行n-1趟,第i趟比较(n-i)次,移动元素3(n-i) 次,这样比较次数为,
1 ( n i ) n( n 1) i 1 2
n 1
移动元素次数为3n(n-1)/2。 最坏情况下的时间复杂度为O(n2)。 冒泡排序是稳定的排序方法。
果在某一趟排序中未交换元素,说明子序列已经有序,则
不再进行下一趟排序。
0 1 2 3 4 5 6
(72, 12,36,48,48,68,02) (02, 12,36,48,48,68)72 (02, 12,36,48,48,68)72
(48,36,68,72,12,48,02) (36,48,68,72,12,48,02) (36,48,68,72,12,48,02) (36,48,68,72,12,48,02) (36,48,68,12,72,48,02) (36,48,68,12,48,72,02) (36,48,68,12,48,02,72) (36,48,68,12,48,02) (36,48,12,48,02)68, (36,12,48,02)48,68, (12,36,02)48,48,68, (12,02)36,48,48,68, (02)12,36,48,48,68, 72 72 72 72 72 72
[2],3,1,3: [2,3],1,3 为何变成了不稳定的? [1,2,3],3 [1,2,3,3]
10.2.3 冒泡排序
基本思想:第1趟在序列(A[0]A[n-1])中从前往后进 行两个相邻元素的比较,若后者小,则交换,比较n-1次。 第1趟排序结束,最大元素被交换到A[n-1]中(即沉底)。 下一趟排序只需在子序列(A[0]A[n-2])中进行。如
2.1 简单排序算法 本节介绍三种简单的排序 算法: 简单选择排序 直接插入排序 冒泡排序 它们的时间复杂度在 最坏情况下均为O(n2)。
相关文档
最新文档