第八讲 排序算法 —— C++ 实现.

Slides:



Advertisements
Similar presentations
3 的倍数的特征 的倍数有 : 。 5 的倍数有 : 。 既是 2 的倍数又是 5 的倍数有 : 。 12 , 18 , 20 , 48 , 60 , 72 , , 25 , 60 ,
Advertisements


数的顺序 比较大小 3 、口答 ( 1 )一个两位数,个位上是 7 ,十位上是 6 , 这个数是( )。 ( 2 )一个数,百位上是 1 ,十位、个位上都 是 0 ,这个数是( )。 1 、读数: 43 、 55 、 67 、 100 、 91 2 、写数:五十二、八十九、四十、七十三、一百.
第四单元 100 以内数的认识
人教新课标一年级数学下册. 教学目标 1. 初步掌握 100 以内数的顺序。 2. 初步会比较 100 以内数的大小。 3. 初步结合具体事物,使同学们 感 受 100 以内数的意义,会用 100 以 内的数表示日常生活中的事物, 并进行简单的估计和交流。
1 、会利用数射线比较 100 以内数的大小。 2 、通过解决与生活相关的实际问题, 使 学生感受数的大小比较在现实生活中的 重要作用, 发展学生的应用意识。 3 、充分感受比较策略的多样化, 学会比 较数的大小, 培养学生的数感。
第四单元 100 以内数的认识
练一练: 在数轴上画出表示下列各数的点, 并指出这些点相互间的关系: -6 , 6 , -3 , 3 , -1.5, 1.5.
回顾上节课的内容 二分 有序 堆 平方级排序算法简单介绍 交换排序 冒泡排序 插入排序 选择排序.
第十章 排序 排序定义——将一个数据元素(或记录)的任意序列,重新排列成一个按关键字有序的序列叫~ 排序分类 按待排序记录所在位置
C语言程序设计.
<<软件技术基础>>
第9章 内部排序 概述 插入排序 (直接插入、折半插入、表插入排序、希尔排序) 交换排序 (起泡排序、快速排序)
第10章 排序.
第九章 排序 课前导学 9.1 排序的基本概念 9.2 插入类排序 9.3 交换类排序 9.4 选择类排序 9.5 归并排序
C++中的声音处理 在传统Turbo C环境中,如果想用C语言控制电脑发声,可以用Sound函数。在VC6.6环境中如果想控制电脑发声则采用Beep函数。原型为: Beep(频率,持续时间) , 单位毫秒 暂停程序执行使用Sleep函数 Sleep(持续时间), 单位毫秒 引用这两个函数时,必须包含头文件
Hadoop I/O By ShiChaojie.
第十章 排序 10.1排序的基本概念 10.2简单排序方法(复杂度 O(n2))
第十章 内部排序.
本章重点难点 重点:插入排序、快速排序、选择排序、归并排序、基数排序的思想和算法。
强连通分量 无向图 1、任意两顶点连通称该图为连通图 2、否则将其中的极大连通子图称为连通分量 A D C B E 有向图
第九章 排序 9.1排序的基本概念 9.2简单排序方法(复杂度 O(n2)) 9.3先进排序方法(复杂度 O(nLogn))
走进编程 程序的顺序结构(二).
辅导课程六.
第2讲 绪论(二).
第一单元 初识C程序与C程序开发平台搭建 ---观其大略
What have we learned?.
第九章 排序 (Sort)
本节内容 模拟线程切换 视频提供:昆山滴水信息技术有限公司 官网地址: 论坛地址: QQ交流 :
动态规划(Dynamic Programming)
Chapter14 Divide and Conquer
第九章 排序 概述 插入排序 交换排序 选择排序 归并排序 *基数排序 *外排序.
顺序表的插入.
使用矩阵表示 最小生成树算法.
第十章内部排序 概述 插入排序 快速排序 选择排序 归并排序 基数排序.
C++语言程序设计 C++语言程序设计 第七章 类与对象 第十一组 C++语言程序设计.
专题作业.
顺序表的删除.
线 性 代 数 厦门大学线性代数教学组 2019年4月24日6时8分 / 45.
第二章 Java基本语法 讲师:复凡.
用计算器开方.
第4章 Excel电子表格制作软件 4.4 函数(一).
C qsort.
小数的大小比较 仙岩镇第二小学 陈曼丽.
§6.7 子空间的直和 一、直和的定义 二、直和的判定 三、多个子空间的直和.
3.16 枚举算法及其程序实现 ——数组的作用.
1.2 子集、补集、全集习题课.
第4课时 绝对值.
多层循环 Private Sub Command1_Click() Dim i As Integer, j As Integer
詹卫东 第九讲 中文姓名识别 詹卫东
第七、八次实验要求.
第九章 排序 东南大学计算机学院 方效林 本课件借鉴了清华大学殷人昆老师 和哈尔滨工业大学张岩老师的课件.
2019/5/21 实验一 离散傅立叶变换的性质及应用 实验报告上传到“作业提交”。 11:21:44.
实验目的:掌握数据的顺序存储结构及它们在计算机中的操作。 实验内容:
生 物 信 息 学 Bioinformatics 巩晶 癌症研究中心 山东大学 医学院
第10章 排序 排序的基本概念 插入排序 选择排序 交换排序归并排序 基数排序 性能比较 主要知识点.
3-3 随机误差的正态分布 一、 频率分布 在相同条件下对某样品中镍的质量分数(%)进行重复测定,得到90个测定值如下:
找 因 数.
主讲人: 吕敏 { } Spring 2012 ,USTC 算法基础 主讲人: 吕敏 { } Spring 2012 ,USTC.
3.4 角的比较.
第十七讲 密码执行(1).
第十二讲 密码执行(上).
插入排序的正确性证明 以及各种改进方法.
使用Fragment 本讲大纲: 1、创建Fragment 2、在Activity中添加Fragment
§4.5 最大公因式的矩阵求法( Ⅱ ).
第二次课后作业答案 函数式编程和逻辑式编程
8、9的认识 一年级组 李 晶.
一元一次方程的解法(-).
最小生成树 最优二叉树.
§2 自由代数 定义19.7:设X是集合,G是一个T-代数,为X到G的函数,若对每个T-代数A和X到A的函数,都存在唯一的G到A的同态映射,使得=,则称G(更严格的说是(G,))是生成集X上的自由T-代数。X中的元素称为生成元。 A变, 变 变, 也变 对给定的 和A,是唯一的.
Presentation transcript:

第八讲 排序算法 —— C++ 实现

排序算法 排序 (Sorting):将一串数据依照指定方式进行排列。 常用排序方式:数值顺序,字典顺序。 时间复杂度(最差、平均): 设有 n 个数据,一般来说,好的排序算法性能是 O(n log n),差的性能是 O(n2),而理想的性能是 O(n)。 空间复杂度: 算法在运行过程中临时占用存储空间的大小。 稳定排序算法:相等的数据维持原有相对次序

常见排序算法 O(n log n) O(n1.5) O(n · k) O(n + k) O(n + D) 算法 平均时间复杂度 选择排序 归并排序 O(n log n) 插入排序 堆排序 希尔排序 O(n1.5) 图书馆排序 冒泡排序 基数排序 O(n · k) 快速排序 桶排序 O(n + k) 计数排序 鸽巢排序 O(n + D) … … … …

主要内容 选择排序 插入排序 希尔排序 冒泡排序 快速排序 本讲中假定是对数据进行从小到大排序

一、选择排序 —— 有时也称为最小排序 找出最小值,将其与第一个位置的元素进行交换, 然后对剩余的序列重复以上过程,直至排序结束。

一、选择排序 原始序列: 2 8 3 12 5 20 7 14 5 16 第1轮排序:2 8 3 12 5 20 7 14 5 16 第2轮排序:2 3 8 12 5 20 7 14 5 16 第3轮排序:2 3 5 12 8 20 7 14 5 16 第4轮排序:2 3 5 5 8 20 7 14 12 16 第5轮排序:2 3 5 5 7 20 8 14 12 16 第6轮排序:2 3 5 5 7 8 20 14 12 16 第7轮排序:2 3 5 5 7 8 12 14 20 16 第8轮排序:2 3 5 5 7 8 12 14 20 16 第9轮排序:2 3 5 5 7 8 12 14 16 20 MATLAB 演示:sort_min.m

选择排序 C++程序 // 找出最小值所在的位置 int findmin(int *px, int n) { int idx=0, xmin=*px; for (int i=1; i<n; i++) if (*(px+i)<xmin) { xmin=*(px+i); idx=i; } return idx; } // 选择排序(最小排序) void sort_min(int *px, int n) { int idx, t; for(int k=0; k<n; k++) { idx=findmin(px+k,n-k); t=px[k]; px[k]=px[k+idx]; px[k+idx]=t; % 交换 }

选择排序 C++程序 sort_min.cpp sort_min100000.cpp int main() { int x[]={2, 8, 3, 12, 5, 20, 7, 14, 5, 16}; int n, i; // 获取数据个数 n = sizeof(x)/sizeof(x[0]); cout << "x=\n"; // 输出原始数据 for(i=0;i<n;i++) cout << setw(3) << x[i]; cout << endl; sort_min(x, n); // 排序 cout << "排序后:\n"; // 输出排序后结果 return 0; } sort_min.cpp sort_min100000.cpp

二、插入排序 基本思想描述如下: 假设前面 k 个元素已经按顺序排好了,在排第 k+1 个 元素时,将其插入到前面已排好的 k 个元素中,使得 插入后得到的 k+1 个元素组成的序列仍按值有序。 然后采用同样的方法排第 k+2 个元素。 以此类推,直到排完序列的所有元素为止。

二、插入排序 原始序列: 2 8 3 12 5 20 7 14 5 16 第1轮排序:2 8 3 12 5 20 7 14 5 16 第2轮排序:2 3 8 12 5 20 7 14 5 16 第3轮排序:2 3 8 12 5 20 7 14 5 16 第4轮排序:2 3 5 8 12 20 7 14 5 16 第5轮排序:2 3 5 8 12 20 7 14 5 16 第6轮排序:2 3 5 7 8 12 20 14 5 16 第7轮排序:2 3 5 7 8 12 14 20 5 16 第8轮排序:2 3 5 5 7 8 12 14 20 16 第9轮排序:2 3 5 5 7 8 12 14 16 20 MATLAB 演示:sort_insert.m

插入排序 C++ 程序 关键点:如何将第 k+1 个元素插入到前面的有序序列中 假定序列为 x1, x2, …, xk, xk+1, … 策略:将 xk+1 依次与 xk, xk-1, … 进行比较,直至遇见第一个 不大于 xk+1 的元素为止。 优化:可以将比较与移位同时进行。

插入排序 C++ 程序 以第 4 轮为例 操作对象 x[k] 比较方向 2 3 8 12 5 20 7 14 5 16 ①先比较 ②后移位

插入排序 C++ 程序 void sort_insert(int * px, int n) 留作练习 // 插入排序(部分代码) ... ... for(k=1; k<n; k++) { key = x[k]; for (i=k-1; x[i]>key && i>=0; i--) x[i+1] = x[i]; } x[i+1] = key; void sort_insert(int * px, int n) 留作练习

三、希尔排序 又称为“缩小增量排序”(Diminishing Increment Sort),由 D. Shell 于1959年提出,是对插入排序的改进。

三、希尔排序 基本过程描述如下: 把序列按照某个增量(gap)分成几个子序列,对这几个 子序列进行插入排序。 不断缩小增量,扩大每个子序列的元素数量,并对每个 子序列进行插入排序。 当增量为 1 时,子序列就是整个序列,而此时序列已经 基本有序了,因此只需做少量的比较和移动就可以完成 对整个序列的排序。 出发点:插入排序在元素基本有序的情况下,效率很高 gap:初始值设为 n/2,然后不断减半。

三、希尔排序 2 8 3 12 5 20 7 14 5 16 第一轮:gap=10/2=5 2 8 3 12 5 20 7 14 16 第一轮排序后 2 7 3 5 20 8 14 12 16

三、希尔排序 2 7 3 5 5 20 8 14 12 16 第二轮:gap=gap/2=2 2 7 3 5 20 8 14 12 16 第二轮排序后 2 5 3 7 14 8 16 12 20

三、希尔排序 2 5 3 7 5 14 8 16 12 20 第三轮:gap=gap/2=1 第三轮排序后 2 3 5 5 7 8 12 在最坏的情况下,插入排序需要 O(n2)次移位操作,而希尔排序只需 O(n log n) 次移位操作。 例:以 n=8 为例,统计最坏情况下插入排序与希尔排序的移位操作次数 MATLAB 演示:sort_shell.m

希尔排序 C++程序 void sort_shell(int * px, int n) 留作练习

四、冒泡排序 基本过程描述如下: 走访需要排序的序列,比较相邻的两个元素,如果他们 的顺序错误就把他们交换过来。 不断重复上述过程,直到没有元素需要交换,排序结束。 这个算法的名字由来是因为越大的元素会经由交换慢慢“浮” 到数列的顶端。

四、冒泡排序 x5 x4 x3 x2 x1 8 14 16 5 20 8 14 16 20 5 8 14 20 16 5 8 20 14 16 5 20 8 14 16 5 MATLAB 演示:sort_bubble.m

四、冒泡排序 具体过程可以描述为: 将第 1 个和第 2 个元素进行比较,如果前者大于后者,则交 换两者的位置,否则位置不变;然后将第 2 个元素与第 3 个 元素进行比较,如果前者大于后者,则交换两者的位置,否 则位置不变;依此类推,直到最后两个元素比较完毕为止。 这就是第一轮冒泡过程,这个过程结束后,最大的元素就 “浮”到了最后一个位置上。 对前面 n-1 个元素进行第二轮冒泡排序,结束后,这 n-1 个 元素中的最大值就被安放在了第 n-1个位置上。 对前面的 n-2个元素进行第三轮冒泡排序。 以此类推,当执行完第 n-1 轮冒泡过程后,排序结束。

冒泡排序 C++ 程序 冒泡排序的优化:如果在某轮冒泡过程中没有发生元素交换,这说明整个序列已经排好序了,这时就不用再进行后面的冒泡过程,可以直接结束程序。 冒泡排序的进一步优化:如果有100个数的数组,仅前面10个无序,后面90个都已排好序且都大于前面10个数字,那么在第一轮冒泡过程后,最后发生交换的位置必定小于10,且这个位置之后的数据必定已经有序了,记录下这位置,第二次只要从数组头部遍历到这个位置就可以了。 void sort_bubble(int * px, int n) 留作练习

五、快速排序 —— 是目前最常用的排序算法之一 快速排序采用的是分而治之思想:将原问题分解为若干个 规模更小但结构与原问题相似的子问题,然后递归求解这 些子问题,最后将这些子问题的解组合为原问题的解。

五、快速排序 具体过程可以描述为: 随机选定其中一个元素作为基准数(pivot)(通常采用 第一个元素),然后通过循环和比较运算,将原序列分割成 两部分,使得新序列中在该基准数前面的元素都小于等于这 个元素,而其后面的元素都大于等于这个元素。(这时基准 数已经归位) 依此类推,再对这两个分割好的子序列进行上述过程, 直到排序结束。(递归思想,分而治之)

快速排序 原始序列: 6 1 3 7 5 9 2 4 8 10 第一步的具体实现方法:(假定基准数的原始位置是 i1=1) 从 i1 右边的位置开始,往右找出第一个大于 6 的数,然后 将该数与基准数交换位置,设基准数新位置为 i3 从 i2 左边的位置开始,往左找出第一个小于 6 的数,然后 将该数与基准数交换位置,设基准数新位置为 i4 从 i3 右边的位置开始,往右找出第一个大于 6 的数,然后 将该数与基准数交换位置,设基准数新位置为 i5 不断重复以上过程,遍历整个序列

快速排序举例 原始序列: 6 1 3 7 5 9 2 4 8 10 第一步: 我们选第一个元素为基准数,即将 6 作为基准数。我们的目标是得到一个新序列,使得在这个新序列中,排在 6 前面的数字都小于 6,而排在 6 后面的数字都不小于 6。 6 1 3 7 5 9 2 4 8 10 基准数 需交换位置的数 搜索 i1=1 搜索起始位置

举例:第一步 6 1 3 7 5 9 2 4 8 10 新序列: 4 1 3 7 5 9 2 6 8 10 i1=1 i2=8

举例:第一步 新序列: 4 1 3 7 5 9 2 6 8 10 搜索 4 1 3 7 5 9 2 6 8 10 i1=1 需交换位置的数 基准数 i2=8 新序列: 4 1 3 6 5 9 2 7 8 10 i3=4 25

举例:第一步 第一步结束! i3=4 i2=8 i4=7 i5=6 4 1 3 6 5 9 2 7 8 10 4 1 3 2 5 9 6 7

举例:第二步 第二步: 对基准数所在位置前面的子序列和后面的子序列,分别重复第一步的过程。 4 1 3 2 5 6 9 7 8 10 2 1

不断重复:递归 2 1 3 4 5 6 8 7 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 排序结束! MATLAB 演示:sort_quick.m

快速排序 C++ 程序 事实上,在快速排序每一步执行过程中,可以不用交换,而是直接覆盖即可,如何实现? 快速排序还有很多改进版本,如随机选择基准数,区间内数据较少时直接用其它的方法排序以减小递归深度等等。有兴趣的同学可以深入研究。 void sort_quick(int* px, int left, int right) 留作练习

上机作业 编写插入排序的 C++ 程序,程序取名 hw08_01.cpp 排序函数名:void sort_insert(int* px, int n) 编写 Shell 排序的 C++ 程序,程序取名 hw08_02.cpp 排序函数名: sort_shell(int* px, int n) (3) 编写冒泡排序的 C++ 程序,程序取名 hw08_03.cpp 排序函数名: sort_bubble(int* px, int n) (4) (选作题) 编写快速排序的 C++ 程序, 程序取名 hw08_04.cpp sort_quick(int* px, int left, int right)