第十章 排序 10.1排序的基本概念 10.2简单排序方法(复杂度 O(n2))

Slides:



Advertisements
Similar presentations
回顾上节课的内容 二分 有序 堆 平方级排序算法简单介绍 交换排序 冒泡排序 插入排序 选择排序.
Advertisements

主讲:计算机工程学院 李兰 答疑地点:主教学楼B区213
数据结构及应用算法教程(修订版) 配套课件.
第十章 内部排序 知识点3:快速排序.
第十章 排序 排序定义——将一个数据元素(或记录)的任意序列,重新排列成一个按关键字有序的序列叫~ 排序分类 按待排序记录所在位置
第九章 排序 插入排序 交换排序 选择排序 归并排序 基数排序.
9.1 概述 9.2 插入排序 9.3 交换排序 9.4 选择排序 9.5 归并排序 9.6 基数排序 9.7 各种内部排序的比较
数据结构 第10章 内部排序.
常宝宝 北京大学计算机科学与技术系 数据结构(七) 常宝宝 北京大学计算机科学与技术系
C语言程序设计.
<<软件技术基础>>
第十章 内部排序 £10.1 概述 £10.5 归并排序 £10.2 插入排序 £10.6 基数排序 £10.3 快速排序
数据结构 第七章 排序.
第9章 内部排序 概述 插入排序 (直接插入、折半插入、表插入排序、希尔排序) 交换排序 (起泡排序、快速排序)
第八章 查找.
第十章 内部排序 10.1 概述 10.2 插入排序 直接插入排序 其他插入排序 希尔排序
第10章 排序.
第九章 排序 课前导学 9.1 排序的基本概念 9.2 插入类排序 9.3 交换类排序 9.4 选择类排序 9.5 归并排序
Chapter 7 Search.
第十章 内部排序.
第8章 排序.
10.1 概述 插入排序 快速排序 堆排序 归并排序 基数排序
10.1、基本概念 10.2、插入排序 10.3、快速排序 10.4、选择排序 10.5、归并排序 10.6、基数排序 10.7、讨论
第十章 排序.
第九章 排序 概述 插入排序 交换排序 选择排序 归并排序 基数排序 外排序.
排序 Sorting.
第九章 排序 9.1排序的基本概念 9.2简单排序方法(复杂度 O(n2)) 9.3先进排序方法(复杂度 O(nLogn))
快速排序法 (Quick Sort).
第9章 排序.
第十章 内部排序.
本章重点难点 重点:插入排序、快速排序、选择排序、归并排序、基数排序的思想和算法。
1、基本概念 2、插入排序 3、交换排序 4、选择排序 5、归并排序 6、基数排序 7、外部排序
第九章 排序 9.1排序的基本概念 9.2简单排序方法(复杂度 O(n2)) 9.3先进排序方法(复杂度 O(nLogn))
第9章 排序 9.1 排序的基本概念 9.2 插入排序 9.3 选择排序 9.4 交换排序 9.5 归并排序 9.6 基数排序.
第九章 查找 2018/12/9.
本章重点难点 重点:顺序查找、二分查找、二叉排序树查找以及散列表查找的基本思想和算法实现。
第 3 讲 线性表(一).
数据结构 复习课 王彦 博士,副教授
中央广播电视大学开放教育试点课程 数据结构 辅导教师 倪政林.
第九章 排序 (Sort)
第9章 内部排序 9.1 概述 9.2 插入排序 9.3 快速排序 9.4 选择排序 9.5 归并排序 9.6 基数排序
第8章 排序 北京师范大学 教育技术学院 杨开城.
数据结构 本 章 说 明 10.1 概 述 10.2 插入排序 10.3 快速排序 10.4 堆 排 序 10.5 归并排序
数据结构 Data Structure CSU 主讲人:王国军,郑瑾 中南大学信息院计科系
数据结构 第八章 查找.
第九章 排序 概述 插入排序 交换排序 选择排序 归并排序 *基数排序 *外排序.
顺序表的插入.
王玲 第 2 章 线性表 王玲 2019/2/25.
第十章内部排序 概述 插入排序 快速排序 选择排序 归并排序 基数排序.
教 师:曾晓东 电 话: E_mail: 计算机软件技术基础 教 师:曾晓东 电 话: E_mail:
3.1 线性表及逻辑结构 3.2 线性表的顺序存储 3.3 线性表的链式存储 3.4 链式存储结构的应用
ACM 程序设计(一) 主讲:朱佳 博士 华南师范大学计算机学院.
C++语言程序设计 C++语言程序设计 第七章 类与对象 第十一组 C++语言程序设计.
计算机软件技术基础 数据结构与算法(5).
第8章 排序 本章中主要介绍下列内容: 插入排序 交换排序 选择排序 归并排序 基数排序.
顺序表的删除.
第九章 排序 概述 插入排序 快速排序 交换排序(起泡排序) 选择排序 归并排序.
9.1 基本概念 9.2 线性表的查找 9.3 树表的查找 9.4 哈希表的查找 9.5 各种查找方法的比较
顺序查找.
Ch.9 查找 §9.1 基本概念 查找和排序是两个重要的运算
C qsort.
<编程达人入门课程> 本节内容 为什么要使用变量? 视频提供:昆山爱达人信息技术有限公司 官网地址: 联系QQ:
10.3 (交换)快 速 排 序(知识点二) 一、起泡排序 二、一趟快速排序 三、快速排序 四、快速排序的时间分析.
第九章 排序 东南大学计算机学院 方效林 本课件借鉴了清华大学殷人昆老师 和哈尔滨工业大学张岩老师的课件.
排序查找 概述 插入排序 交换排序 选择排序 归并排序 主讲:朱佳 博士.
第8章 排序 8.1排序基本概念 8.2插入类排序 8.3交换类排序 8.4选择类排序 8.5归并排序 8.6基数排序
第10章 排序 排序的基本概念 插入排序 选择排序 交换排序归并排序 基数排序 性能比较 主要知识点.
插入排序的正确性证明 以及各种改进方法.
算法的基本思想: 第6章 内部排序 6.2 气泡排序 将待排序的记录看作是竖着排列的“气泡”,关键字较小 的记录比较轻,从而要往上浮。
排序 排序(sorting)是计算机程序设计中的一种重要操作,它的功能是将一个数据元素(或记录)的任意序列,重新排列成一个按关键字有序的序列。 由于待排序的记录数量不同,使得排序过程中涉及的存储器不同,可将排序方法分为两大类:一类是内部排序,指的是待排序记录存放在计算机存储器中进行的排序过程;另一类是外部排序,指的是待排序记录的数量很大,以致内存一次不能容纳全部记录,在排序过程中对外存进行访问的排序过程。
Presentation transcript:

第十章 排序 10.1排序的基本概念 10.2简单排序方法(复杂度 O(n2)) 10.3先进排序方法(复杂度 O(nLogn) /O(n3/2)) 10.4基数排序(复杂度 O(d×n)) 10.5各种排序的综合比较

10.1排序的基本概念 排序单元结构定义 例: Typedef struct { char name[10]; char sex[2]; typedef int KeyType; //简单起见,只要可比就可以 typedef struct{ KeyType key; InfoType otherinfo; }RcdType; 例: Typedef struct { char name[10]; char sex[2]; char birthday[8]; char department[4]; }InfoType

Typedef struct{ RcdType r[MAXSIZE+1]; Int length; }Sqlist; 排序 稳定与不稳定排序 设N个记录 {r1,r2…rn}, 相应关键字{k1,k2…kn} 求一种排列p1,p2…pn,使得kp1≤kp2≤…≤kpn 即{rp1,rp2…rpn}是按关键字有序序列 稳定与不稳定排序 若ki=kj,并且在待排序列中ri领先于rj (即i<j),若排序后的序列中ri仍然领先 rj,则称该排序方法稳定。 内部排序与外部排序 内部排序:仅在内部存储器中完成的排序 外部排序:在排序中需要访问外部存储器的排序 本章排序操作对象: Typedef struct{ RcdType r[MAXSIZE+1]; Int length; }Sqlist;

10.2简单排序方法(复杂度 O(n2)) 10.2.1选择排序 void SelectPass(Sqlist &L,int i)复杂度 O(n) void SelectSort(Sqlist &L)复杂度 O(n2) n(n+1)/2次比较和3(n-1)次交换。 本身是稳定算法,本例由交换引起不稳定,可采用移动策略获稳定算法 R[i] R[j] 有序序列R[1..i-1] 无序序列R[i..n] 有序序列R[1..i] 无序序列R[i+1..n]

选择排序(一趟) void SelectPass( SqList &L, int i ) { RcdType W; j = i; //j为最小值位置 for ( k=i+1; k<=L.length; k++ ) if ( L.r[k].key < L.r[j].key ) j = k ; if ( i != j ) { W=L.r[j];L.r[j] =L.r[i];L.r[i] = W;} } // SelectPass

选择排序 void SelectSort (SqList &L) { for (i=1; i<L.length; ++i) { RcdType W; for (i=1; i<L.length; ++i) { j = i; for ( k=i+1; k<=L.length; k++ ) if ( L.r[k].key < L.r[j].key ) j =k ; if ( i!=j ) { W=L.r[j];L.r[j] =L.r[i];L.r[i] = W;} } } // SelectSort

10.2.2插入排序 数据的有序性影响算法 最差比较移动 (n+4)(n-1)/2 是稳定排序 R[i] void InsertPass(Sqlist &L,int i)复杂度 O(n) void InsertSort(Sqlist &L) 复杂度 O(n2) 数据的有序性影响算法 最差比较移动 (n+4)(n-1)/2 是稳定排序 R[i] 有序序列R[1..i-1] 无序序列R[i..n] 有序序列R[1..i] 无序序列R[i+1..n]

插入排序(一趟) void InsertPass( SqList &L, int i ) { 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]; // 插入到正确位置 } // InsertPass

插入排序 void InsertSort ( 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]; // 插入到正确位置 } // if } // InsertSort

其他插入排序 折半插入: 2路插入: 表插入: 插入时因为有序区可以使用折半查找,从而提 高插入速度 为了减少移动,分两个半区插入,可以和折半一起使用 表插入: 通过静态链表形式存储数据元素,通过修改指针的方式避免元素的移动,不可以使用折半插入。

10.2.3起泡排序 有序序列的比较次数是n-1次 逆序序列的比较次数是 n(n-1)/2;移动次数3n(n-1)/2 是稳定排序 R[i] void BubbleSort(Sqlist &L)复杂度 O(n2) 有序序列的比较次数是n-1次 逆序序列的比较次数是 n(n-1)/2;移动次数3n(n-1)/2 是稳定排序 R[i] 有序序列R[i+1..n] 无序序列R[1..i] 有序序列R[i..n] 无序序列R[1..i-1]

起泡排序 void BubbleSort( SqList &L ){ i = L.length; while (i >1) { lastExchangeIndex = 1; for (j = 1; j < i; j++){ if (L.r[j+1].key < L.r[j].key) { W=L.r[j];L.r[j] =L.r[j+1];L.r[j+1] = W; lastExchangeIndex = j; } //if } //for i = lastExchangeIndex; } // while } // BubbleSort

10.3先进排序方法 10.3.1快速排序 void Partition 一趟快速排序(分割) void Qsort(RcdType R[],int s,int t)递归函数 void QuickSort(SqList &L)快速排序 时间复杂度 O(nLogn) 最坏情况有序O(n2) 空间复杂度 O(logn) 改进:取中原则:R[s],R[t],R[(s+t)/2]

快速排序(分割) int Partition ( RcdType R[], int low, int high) { R[0] = R[low]; // 将枢轴记录移至数组的闲置分量 pivotkey = R[low].key; // 枢轴记录关键字 while (low<high) { // 从表的两端交替地向中间扫描 while(low<high&& R[high].key>=pivotkey) --high; R[low++] = R[high]; // 将比枢轴记录小的记录移到低端 while (low<high && R[low].key<=pivotkey) ++low; R[high--] = R[low]; // 将比枢轴记录大的记录移到高端 } //while R[low] = R[0]; // 枢轴记录移到正确位置 return low; // 返回枢轴位置 } // Partition

快速排序 void QSort (RedType R[], int s, int t ) { // 对记录序列R[s..t]进行快速排序 if (s < t) { // 长度大于1 pivotloc = Partition(R, s, t);// 对 R[s..t]一分为二 QSort(R, s, pivotloc-1); // 对低子序列递归排序 QSort(R, pivotloc+1, t); // 对高子序列递归排序 } // if } // Qsort void QuickSort( SqList & L) { QSort(L.r, 1, L.length); } // QuickSort

10.3.2归并排序 void Merge (RcdType SR[], RcdType TR[], int i, int m, int n) void Msort ( RcdType SR[], RcdType TR1[], int s, int t ) 递归函数 void MergeSort(SqList &L)快速排序 时间复杂度 O(nLogn) 空间复杂度 O(n)

归并排序(一趟) void Merge (RcdType SR[], RcdType TR[], int l, int m, int n) { // 将有序的SR[l..m]和SR[m+1..n]归并为有序的TR[l..n] for (i=l,j=m+1, k=l; i<=m && j<=n; ++k) { if (SR[i].key<=SR[j].key) TR[k] = SR[i++]; else TR[k] = SR[j++]; } while (i<=m) TR[k++] = SR[i++]; while (j<=n) TR[k++] = SR[j++]; } // Merge

归并排序 void Msort ( RcdType SR[], RcdType TR1[], int s, int t ) { // 对SR[s..t]进行归并排序,排序后的记录存入TR1[s..t]。 if (s==t) TR1[s] = SR[s]; else { m = (s+t)/2; Msort (SR, TR2, s, m); Msort (SR, TR2, m+1, t); Merge (TR2, TR1, s, m, t); } // else } // MSort void MergeSort (SqList &L) { MSort(L.r, L.r, 1, L.length); } // MergeSort

2路归并排序程序 1)一趟排序 void mergepass(RcdType SR[],RcdType TR[],int s,int n){ while(i+2s-1<=n) { merge(SR,TR,i,i+s-1,i+2*s-1); i +=2*s; } if(i+s-1<n) //最后还有两个集合,但不等长 merge(SR,TR,i,i+s-1,n); else //最后还有一个集合 while(i<=n){TR[i]=SR[i];i++};

2路归并排序程序(2) 2) 2路归并 void mergesort((Sqlist &L){ RcdType TR[L.length+1]; s=1; while(s<n){ mergepass(L.r,TR,s,n); s*=2; mergepass(TR,L.r,s,n); s*=2; }

10.3.3堆排序 小顶堆: ri<r2i; ri<r2i+1 大顶堆 :ri>r2i, ri>r2i+1 时间复杂度 O(nLogn)  空间复杂度 O(1)

void HeapAdjust(HeapType &H, int s, int m) { // 算法10.10 // 已知H.r[s..m]中记录的关键字除H.r[s] 之外均满足堆的定义, rc = H.r[s]; for (j=2*s; j<=m; j*=2) { // 沿key较大的孩子结点向下筛选 if (j<m && H.r[j].key<H.r[j+1].key) ++j; // j为key较大的记录的下标 if (rc.key >= H.r[j].key) break; // rc应插入在位置s上 H.r[s] = H.r[j]; s = j; }//for H.r[s] = rc; // 插入 } // HeapAdjust void HeapSort(HeapType &H) { for (i=H.length/2; i>0; --i) HeapAdjust ( H, i, H.length ); for (i=H.length; i>1; --i) {H.r[i] ↔ H.r[1] HeapAdjust(H, 1, i-1); } } // HeapSort

10.3.4希尔排序 又称“缩小增量排序” 初始: 49 38 65 97 76 13 27 49 55 04 49 13 └───────────┘ 38 27 65 49 97 55 76 04 └──────────┘ 一趟排序: 13 27 49 55 04 49 38 65 97 76 └──────┴──────┴──────┘ 27 04 65 └──────┴──────┘ 49 49 97 二趟排序: 13 04 49 38 27 49 55 65 97 76 三趟排序: 04 13 27 38 49 49 55 65 76 97

希尔排序 能用哨卡吗? void ShellInsert(SqList &L, int dk) { for (i=dk+1; i<=L.length; i++) //逐个间隔插入,不分子集 if (LT(L.r[i].key, L.r[i-dk].key)) { for (j=i-dk; j>0 && LT(L.r[j+dk].key, L.r[j].key); j-=dk) L.r[j+dk] = L.r[j]; // 记录后移,查找插入位置 L.r[j+dk] = L.r[0]; // 插入 } } // ShellInsert void ShellSort(SqList &L, int dlta[], int t) { for (int k=0; k<t; ++k) ShellInsert(L, dlta[k]); // 一趟增量为dlta[k]的插入排序 } // ShellSort 能用哨卡吗?

10.3.5树形选择排序 13 38 65 27 49 97 76 27 38 65 76 49 97 ∞ 38 49 65 76 97 ∞ 49 65 76 ∞ 97

10.4基数排序(复杂度 O(d×n)) 逻辑关键字、关键字,关键字分级 对于有d个关键字的记录排序,要进行d趟分配和收集 时间复杂度 O(n×d); 空间复杂度 O(n)

10.5各种排序的综合比较 选择排序方法考虑因素 待排序记录数n 记录本身其他信息量大小 关键字分布情况 稳定性要求 时间性能 按时间性能分三类 :简单、先进、基数 有序性对算法的影响 插入和起泡有好的影响O(n) 快速有坏的影响O(n2) 选择、归并、堆、基数没有影响 记录其他信息复杂度对算法的影响 起泡、快速、堆等移动较多的算法影响较大

空间性能 稳定性 例:(4,3,4,2)进行快速排序不稳定 经过一趟排序能将一个数据放在最终位置 所有简单排序、堆是O(1) 快速是O(Logn) 归并、基数O(n) 稳定性 快速和堆大范围交换的算法不稳定 其他算法均稳定。 例:(4,3,4,2)进行快速排序不稳定 经过一趟排序能将一个数据放在最终位置 选择、起泡、堆

排序的另一种分类 选择排序: 交换排序: 插入排序: 归并排序 基数排序 简单选择、树形选择、堆排序 起泡排序、快速排序 简单插入、折半插入、表插入、希尔排序 归并排序 基数排序

各种排序的综合比较表 选择 O(n2) O(1) Y 无 插入 O(n) 好 起泡 快速 O(nLogn) O(Logn) N 坏 归并 堆 算法 平均时间 最坏情况 最好情况 辅助空间 稳定性 有序性影响 选择 O(n2) O(1) Y 无 插入 O(n) 好 起泡 快速 O(nLogn) O(Logn) N 坏 归并 堆 基数 O(n*d)