第9章 内部排序 9.1 概述 9.2 插入排序 9.3 快速排序 9.4 选择排序 9.5 归并排序 9.6 基数排序

Slides:



Advertisements
Similar presentations
第 8 章 数组 计算机科学学院 李淮 Tel QQ
Advertisements

第 九 章 搜尋(Search) 課程名稱:資料結構 授課老師:_____________.
主讲:计算机工程学院 李兰 答疑地点:主教学楼B区213
数据结构及应用算法教程(修订版) 配套课件.
第十章 内部排序 知识点3:快速排序.
第九章 排序 插入排序 交换排序 选择排序 归并排序 基数排序.
9.1 概述 9.2 插入排序 9.3 交换排序 9.4 选择排序 9.5 归并排序 9.6 基数排序 9.7 各种内部排序的比较
第8章 查找 在英汉字典中查找某个英文单词的中文解释;在新华字典中查找某个汉字的读音、含义;在对数表、平方根表中查找某个数的对数、平方根;邮递员送信件要按收件人的地址确定位置等等。可以说查找是为了得到某个信息而常常进行的工作。 计算机、计算机网络使信息查询更快捷、方便、准确。要从计算机、计算机网络中查找特定的信息,就需要在计算机中存储包含该特定信息的表。如要从计算机中查找英文单词的中文解释,就需要存储类似英汉字典这样的信息表,以及对该表进行的查找操作。本章将讨论的问题即是“信息的存储和查找”。
第八章 查找.
第十章 内部排序 10.1 概述 10.2 插入排序 直接插入排序 其他插入排序 希尔排序
第二章 线性表 1 线性表的逻辑结构及其基本操作 2 线性表的顺序存储结构 3 线性表的链式存储结构 4 静态链表 5 应用实例.
第8章 查找 数据结构(C++描述).
专题研讨课二: 数组在解决复杂问题中的作用
Chapter 7 Search.
第6章 佇列(Queues) 6-1 佇列的基礎 6-2 佇列的表示法 6-3 環狀佇列 6-4 雙佇列.
第11章 查找 主要知识点 查找的基本概念 静态查找表 动态查找表 哈希表.
佇列 (Queue).
資料結構 第5章 佇列.
第8章 排序.
第十章 排序.
第九章 排序 概述 插入排序 交换排序 选择排序 归并排序 基数排序 外排序.
Chap 3 堆疊與佇列 Stack and Queue.
排序 Sorting.
第九章 排序 9.1排序的基本概念 9.2简单排序方法(复杂度 O(n2)) 9.3先进排序方法(复杂度 O(nLogn))
快速排序法 (Quick Sort).
第十章 排序 10.1排序的基本概念 10.2简单排序方法(复杂度 O(n2))
第9章 排序.
本章重点难点 重点:插入排序、快速排序、选择排序、归并排序、基数排序的思想和算法。
1、基本概念 2、插入排序 3、交换排序 4、选择排序 5、归并排序 6、基数排序 7、外部排序
搜尋資料結構 Search Structures.
第九章 排序 9.1排序的基本概念 9.2简单排序方法(复杂度 O(n2)) 9.3先进排序方法(复杂度 O(nLogn))
第2章 线性表 2.1 线性表的基本概念 2.2 线性表的顺序存储 2.3 线性表的链式存储 2.4 线性表的应用 2.5 有序表 本章小结.
第2章 线性表 线性表抽象数据类型 顺序表 主要知识点 单链表 循环单链表 循环双向链表 静态链表 设计举例.
第8章 排 序 8.1 排序技术概述 8.2 插入排序 8.3 选择排序 8.4 交换排序 8.5 归并排序 8.6 基数排序
第九章 查找 2018/12/9.
第3章 堆栈和队列 堆栈 堆栈应用 队列 队列应用 优先级队列 主要知识点.
本章重点难点 重点:顺序查找、二分查找、二叉排序树查找以及散列表查找的基本思想和算法实现。
第 3 讲 线性表(一).
第三章 栈与队列 £3.1 栈 £3.3 队列 £3.2 栈的应用举例 £3.1.1 栈的定义 £3.1.2 栈的顺序存储结构
第三章 栈和队列.
第一章 绪论.
数 据 结 构 Ch.4 串 计 算 机 学 院 肖明军
陈海明 副教授 信息学院 计算机系 电子信息类非计算机专业选修课 程序设计实践 陈海明 副教授 信息学院 计算机系
中央广播电视大学开放教育试点课程 数据结构 辅导教师 倪政林.
数据结构 第9章 查找 什么是查找?? 静态查找 动态查找 哈希表 数据结构.
第九章 查找表 9.1静态查找表 9.2动态查找表 9.3哈希表及其查找.
数据结构 Data Structure CSU 主讲人:王国军,郑瑾 中南大学信息院计科系
第九章 查找 2019/2/16.
第三章 栈和队列.
数据结构 第八章 查找.
严蔚敏、吴伟民编著 清华大学出版社 学习网站:
陈海明 副教授 信息学院 计算机系 电子信息类非计算机专业选修课 程序设计实践 陈海明 副教授 信息学院 计算机系
王玲 第 2 章 线性表 王玲 2019/2/25.
第三节 堆及其应用.
教 师:曾晓东 电 话: E_mail: 计算机软件技术基础 教 师:曾晓东 电 话: E_mail:
3.1 线性表及逻辑结构 3.2 线性表的顺序存储 3.3 线性表的链式存储 3.4 链式存储结构的应用
資料結構與C++程式設計進階 排序與搜尋 講師:林業峻 CSIE, NTU 6/ 14, 2010.
第1章 绪论 2019/4/16.
数据结构选讲 北京大学 陈瑜希.
第九章 排序 概述 插入排序 快速排序 交换排序(起泡排序) 选择排序 归并排序.
9.1 基本概念 9.2 线性表的查找 9.3 树表的查找 9.4 哈希表的查找 9.5 各种查找方法的比较
99高中資訊科選修課程 夥伴學習教師 專業進修研習 進階程式設計--演算法 教學示例與研討
Ch.9 查找 §9.1 基本概念 查找和排序是两个重要的运算
<编程达人入门课程> 本节内容 为什么要使用变量? 视频提供:昆山爱达人信息技术有限公司 官网地址: 联系QQ:
累堆排序法 (Heap Sort).
第8章 排序 8.1排序基本概念 8.2插入类排序 8.3交换类排序 8.4选择类排序 8.5归并排序 8.6基数排序
顺序查找与二分查找复习.
Chapter 2 Entity-Relationship Model
算法的基本思想: 第6章 内部排序 6.2 气泡排序 将待排序的记录看作是竖着排列的“气泡”,关键字较小 的记录比较轻,从而要往上浮。
排序 排序(sorting)是计算机程序设计中的一种重要操作,它的功能是将一个数据元素(或记录)的任意序列,重新排列成一个按关键字有序的序列。 由于待排序的记录数量不同,使得排序过程中涉及的存储器不同,可将排序方法分为两大类:一类是内部排序,指的是待排序记录存放在计算机存储器中进行的排序过程;另一类是外部排序,指的是待排序记录的数量很大,以致内存一次不能容纳全部记录,在排序过程中对外存进行访问的排序过程。
Presentation transcript:

第9章 内部排序 9.1 概述 9.2 插入排序 9.3 快速排序 9.4 选择排序 9.5 归并排序 9.6 基数排序 9.1 概述 9.2 插入排序 9.3 快速排序 9.4 选择排序 9.5 归并排序 9.6 基数排序 9.7 内部排序方法的比较

本章重点难点 重点:插入排序、快速排序、选择排序、归并排序、基数排序的思想和算法。 难点:堆排序的思想和算法,在实际应用中如何根据实际情况,选择最优的排序算法。

第9章 内部排序 9.1 概述 9.2 插入排序 9.3 快速排序 9.4 选择排序 9.5 归并排序 9.6 基数排序 9.1 概述 9.2 插入排序 9.3 快速排序 9.4 选择排序 9.5 归并排序 9.6 基数排序 9.7 内部排序方法的比较

9.1 概述 排序方法的稳定和不稳定 当需要排序的关键字都不相同时,排序的结果是唯一的; 张三 80分 李四 75分 王五 85分 陈六 90分 李四 75分 张三 80分 王五 85分 陈六 90分 陈六 90分 王五 85分 张三 80分 李四 75分

9.1 概述 当排序的关键字中存在相同的情况时,排序方法不唯一; 张三 80分 李四 75分 王五 85分 陈六 80分 李四 75分 张三 80分 陈六 80分 王五 85分 李四 75分 陈六 80分 张三 80分 王五 85分 在排序前后,含相等关键字的记录的相对位置保持不变,称这种排序方法是稳定的; 反之,含相等关键字的记录的相对位置有可能改变,称这种排序方法是不稳定的。

9.1 概述 内部排序和外部排序 在排序过程中,只使用计算机的内存存放待排序记录,称这种排序为内部排序。 排序期间文件的全部记录不能同时存放在计算机的内存中,要借助计算机的外存才能完成排序,称之为“外部排序”。 内外存之间的数据交换次数就成为影响外部排序速度的主要因素。

9.1 概述 存储结构 #define MAXSIZE 1000 // 待排顺序表最大长度 typedef int KeyType; // 关键字类型为整数类型 typedef struct { KeyType key; // 关键字项 InfoType otherinfo; // 其它数据项 } RcdType; // 记录类型 typedef struct { RcdType r[MAXSIZE+1]; // r[0]闲置 int length; // 顺序表长度 } SqList; // 顺序表类型

9.1 概述 效率分析 (1) 时间复杂度: 关键字的比较次数和记录移动次数。 (2) 空间复杂度: 执行算法所需的附加存储空间。 (3) 稳定算法和不稳定算法

第9章 内部排序 9.1 概述 9.2 插入排序 9.3 快速排序 9.4 选择排序 9.5 归并排序 9.6 基数排序 9.1 概述 9.2 插入排序 9.3 快速排序 9.4 选择排序 9.5 归并排序 9.6 基数排序 9.7 内部排序方法的比较

9.2、插入排序 9.2.1 直接插入排序 9.2.2 其他插入排序 9.2.3 希尔排序

9.2.1 直接插入排序 插入排序的思想 (1)一个记录是有序的; (2)从第二个记录开始,将每个记录插入到已排好序的序列中; (3)一直进行到第n个记录。

9.2.1 直接插入排序 算法概述 (1)将序列中的第1个记录看成是一个有序的子序列; (2)从第2个记录起逐个进行插入,直至整个序列变成按关键字有序序列为止; 整个排序过程需要进行比较、后移记录、插入适当位置。从第二个记录到第n个记录共需n-1趟。

9.2.1 直接插入排序 直接插入排序示例演示 49 38 65 38. 76 13 27 38 49 65 38. 76 13 27 38 49 65 38. 76 13 27 38 49 65 38. 76 13 27 65 38 49 38. 76 13 27 38. 38 49 65 76 13 27 38. 38 49 65 76 13 27 38. 38 49 65 76 13 27

9.2.1 直接插入排序 直接插入排序算法 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

9.2.1 直接插入排序 算法分析 (1)稳定性 直接插入排序是稳定的排序方法。 (2)算法效率 a.时间复杂度 最好情况:比较O(n),移动O(1); 最坏情况:比较O(n2),移动O(n2); 平均O(n2) b.空间复杂度 O(1)。

9.2.2 其它插入排序 折半插入排序思想 (1)在直接插入排序中,r[1..i-1] 是一个按关键字有序的有序序列; (2)可以利用折半查找实现“在r[1..i-1]中查找r[i]的插入位置”; (3)称这种排序为折半插入排序。

9.2.2 其它插入排序 折半插入排序的演示过程 0 1 2 3 4 5 6 7 8 9 10 查22 05 13 19 21 37 56 64 75 80 88 90 low mid= (low+high)/2 high mid high=mid-1 low=mid+1 mid low=mid+1 high=mid-1

9.2.2 其它插入排序 折半插入排序算法 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

9.2.2 其它插入排序 折半插入排序算法 low = 1; high = i-1; while (low<=high) { m = (low+high)/2; // 折半 if (L.r[0].key < L.r[m].key) high = m-1; // 插入点在低半区 else low = m+1; // 插入点在高半区 }

9.2.2 其它插入排序 2路插入排序示例演示 分治的思想 排序49, 38, 65, 97, 76, 13, 27, 49* 例 49 9.2.2 其它插入排序 2路插入排序示例演示 分治的思想 排序49, 38, 65, 97, 76, 13, 27, 49* 例 49 49 38 49 65 38 49 65 97 38 49 65 76 97 38 49 65 76 97 13 38 49 65 76 97 13 27 38

9.2.2 其它插入排序 表插入排序的思想 (1)目的是为了减少在排序过程中进行的 “移动”记录的操作; (2)利用静态链表进行排序,排序中只改为指针; (3)在排序完成之后,一次性地调整各个记录相互之间的位置。

9.2.2 其它插入排序 表插入排序的存储结构 #define SIZE 100 typedef struct { RcdType rc; int next; }SLNode; typedef struct { SLNode r[SIZE]; int length; }SLinkListType;

9.2.2 其它插入排序 表插入排序的示例演示 1 2 3 4 5 6 7 8 初始 状态 key域 next域 M 49 38 65 97 1 2 3 4 5 6 7 8 初始 状态 M 49 38 65 97 76 13 27 49* 1 - key域 next域 M 49 38 65 97 76 13 27 49* 2 1 - M 49 38 65 97 76 13 27 49* 2 3 1 - M 49 38 65 97 76 13 27 49* 2 3 1 4 -

9.2.2 其它插入排序 表插入排序的算法 void LInsertionSort (SLinkListType &SL){ // 对记录序列SL[1..n]作表插入排序 SL.r[0].key = MAXINT ; SL.r[0].next = 1; SL.r[1].next = 0; for ( i=2; i<=n; ++i ) for ( j=0, k = SL.r[0].next;SL.r[k].key<= SL.r[i].key ; j=k, k=SL.r[k].next ) { SL[j].next = i; SL[i].next = k; } // 结点i插入在结点j和结点k之间 }// LinsertionSort

9.2.2 其它插入排序 表插入排序的示例演示 i=1 p=6 q=7 i=2 p=7 q=2 i=3 p=2 q=1 i=4 p=1 1 2 3 4 5 6 7 8 i=1 p=6 q=7 M 49 38 65 97 76 13 27 49* 6 8 1 5 4 7 2 3 i=2 p=7 q=2 M 13 38 65 97 76 49 27 49* 6 (6) 1 5 4 8 2 3 i=3 p=2 q=1 M 13 27 65 97 76 49 38 49* 6 (6) (7) 5 4 8 1 3 i=4 p=1 q=8 M 13 27 38 97 76 49 65 49* 6 (6) (7) 4 8 5 3 p=SL.r[p].next

9.2.2 其它插入排序 表插入排序的记录调整算法 void Arrange (SLinkListType &SL) { p = SL.r[0].next; // p指示第一个记录的当前位置 for ( i=1; i<Sl.length; ++i ) { while (p<i) p = SL.r[p].next; q = SL.r[p].next; // q指示尚未调整的表尾 if ( p!= i ) { SL.r[p]←→SL.r[i]; // 交换记录,使第i个记录到位 SL.r[i].next = p; // 指向被移走的记录 } p = q; // p指示尚未调整的表尾, // 为找第i+1个记录作准备 } // Arrange

9.2.3 希尔排序 希尔排序的思想 (1)对待排记录序列先作“宏观”调整,再作“微观”调整。 (2)所谓“宏观”调整,指的是,“跳跃式” 的插入排序。

9.2.3 希尔排序 希尔排序概述 (1)将记录序列分成若干子序列,分别对每个子序列进行插入排序。 例如:将 n 个记录分成 d 个子序列: {R[1],R[1+d],R[1+2d],…,R[1+kd]} {R[2],R[2+d],R[2+2d],…,R[2+kd]} …………………………………… {R[d],R[2d],R[3d],…,R[kd],R[(k+1)d]} (2)其中,d 称为增量,它的值在排序过程中从大到小逐渐缩小,直至最后一趟排序减为 1。

9.2.3 希尔排序 希尔排序演示 16 25 12 30 47 11 23 36 9 18 31 第一趟希尔排序,设增量 d =5 11 23 12 9 18 16 25 36 30 47 31 第二趟希尔排序,设增量 d = 3 9 18 12 11 23 16 25 31 30 47 36 第三趟希尔排序,设增量 d = 1 9 11 12 16 18 23 25 30 31 36 47

9.2.3 希尔排序 希尔排序算法 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)) { L.r[0] = L.r[i]; // 暂存在R[0] for (j=i-dk; j>0&&LT(L.r[0].key,L.r[j].key); j-=dk) L.r[j+dk] = L.r[j]; // 记录后移,查找插入位置 L.r[j+dk] = L.r[0]; // 插入 }

9.2.3 希尔排序 希尔排序算法 void ShellSort (SqList &L, int dlta[], int t) { // 增量为dlta[]的希尔排序 for (k=0; k<t; ++k) ShellInsert(L, dlta[k]); //一趟增量为dlta[k]的插入排序 }

9.2.3 希尔排序 希尔排序算法分析 (1)稳定性 希尔排序是不稳定的排序方法。 (2)算法效率 (1)时间复杂度 平均O(n1.3)到平均O(n1.5) (2)空间复杂度 O(1)。

第9章 内部排序 9.1 概述 9.2 插入排序 9.3 快速排序 9.4 选择排序 9.5 归并排序 9.6 基数排序 9.1 概述 9.2 插入排序 9.3 快速排序 9.4 选择排序 9.5 归并排序 9.6 基数排序 9.7 内部排序方法的比较

9.3 快速排序 9.3.1、起泡排序 9.3.2、快速排序

9.3.1 起泡排序 基本思想 (1)从第一个记录开始,两两记录比较,若F[1].key>F[2].key,则将两个记录交换; (2)第1趟比较结果将序列中关键字最大的记录放置到最后一个位置,称为“沉底”,而最小的则上浮一个位置; (3)n个记录比较n-1遍(趟)。

9.3.1 起泡排序 示例演示 1 6 2 3 4 5 1 2 6 3 4 5 1 2 3 6 4 5 1 2 3 4 6 5 1 2 3 4 5 6 6 1 2 3 4 5 第一趟 1 2 3 4 5 6 第二趟

9.3.1 起泡排序 算法 void BubbleSort(SqList &L ) {int i,j,noswap; SqList temp; for(i=1;i<=n-1;i++) {noswap=TRUE; for(j=1;j<=n-i;j++) if (L.r[j].key>L.r[j+1].key) {temp=L.r[j]; L.r[j]=L.r[j+1]; L.r[j+1]=temp; noswap=FALSE; } if (noswap) break;

9.3.1 起泡排序 算法分析 (1)稳定性 起泡排序是稳定的排序方法。 (2)时间是复杂性 最好情况:比较O(n),移动O(1) 最坏情况:比较O(n2),移动O(n2) 平均情况:O(n2) (3)空间复杂性 O(1)

(1)左侧子序列中所有对象的关键字都小于或等于对象v的关键字; (2)右侧子序列中所有对象的关键字都大于或等于对象v的关键字; 9.3.2 快速排序 基本思想 任取待排序对象序列中的某个对象v(枢轴,基准,支点),按照该对象的关键字大小,将整个序列划分为左右两个子序列; (1)左侧子序列中所有对象的关键字都小于或等于对象v的关键字; (2)右侧子序列中所有对象的关键字都大于或等于对象v的关键字; (3)对象v则排在这两个子序列中间(也是它最终的位置)。

9.3.2 快速排序 示例演示 初始关键字 49 49* 65 97 17 27 50 i j j 一次交换 27 49* 65 97 17 49 50 i i j 二次交换 27 49* 49 97 17 65 50 i j 三次交换 27 49* 17 97 49 65 50 i j 四次交换 27 49* 17 49 97 65 50 i j 完成一趟排序

9.3.2 快速排序 算法关键语句 初始关键字 49 49* 65 97 17 27 50 low high high pivotkey=L.r[low].key; while ((low<high)&& (L.r[high].key>=pivotkey)) --high; L.r[low] ←→ L.r[high]; 一次交换 27 49* 65 97 17 49 50 low high low while ((low<high)&& (L.r[low].key<=pivotkey)) ++low; L.r[low] ←→ L.r[high];

while ((low<high)&& (L.r[high].key>=pivotkey)) --high; 9.3.2 快速排序 算 法 int Partition(SqList &L, int low, int high) { KeyType pivotkey; pivotkey = L.r[low].key; while (low<high) { while ((low<high)&& (L.r[high].key>=pivotkey)) --high; L.r[low] ←→ L.r[high]; while ((low<high)&& (L.r[low].key<=pivotkey)) ++low; } return low; // 返回枢轴位置 } // Partition

9.3.2 快速排序 算法分析 (1)稳定性 快速排序是不稳定的排序方法。 (2)时间复杂度 最坏情况: 1,2,3,…,n n,n-1,…2,1。 比较O(n2), 移动O(n2) n,n-1,…2,1。

9.3.2 快速排序 算法分析 时间复杂性最好情况是每次选择的基准把左右分成相等两部分: C(n)≤n+2C(n/2) ≤n+2(n/2+2C(n/4))=2n+22C(n/22) …… ≤kn+2kC(n/2k) 最后组中只有一个元素:n=2k,k=log2n, C(n)≤nlog2n+nC(1) 最好情况的时间复杂度为O(nlog2n) 平均时间复杂度也是O(nlog2n)

由于快速排序是一个递归过程,需一个栈的附加空间,栈的平均深度为O(log2n)。 9.3.2 快速排序 (3)空间复杂度 由于快速排序是一个递归过程,需一个栈的附加空间,栈的平均深度为O(log2n)。 QUICKSORT(s,t,A) LIST F; int s,t; {int i; if (s<t) {i=PARTITION(s,t,A); QUICKSORT(s,i-1,A); QUICKSORT(i+1,t,A); } 假如数组元素下标为1…n。 1 … n/2k n/2k-1 n/23 n/4 n/22 n/2 n

第9章 内部排序 9.1 概述 9.2 插入排序 9.3 快速排序 9.4 选择排序 9.5 归并排序 9.6 基数排序 9.1 概述 9.2 插入排序 9.3 快速排序 9.4 选择排序 9.5 归并排序 9.6 基数排序 9.7 内部排序方法的比较

9.4 选择排序 9.4.1 简单选择排序 9.4.2 树形选择排序 9.4.3 堆排序

9.4.1 简单选择排序 基本思想 (1)第一次从n个关键字中选择一个最小值,确定第一个; (2)第二次再从剩余元素中选择一个最小值,确定第二个; (3)共需n-1次选择。

9.4.1 简单选择排序 操作过程 设需要排序的表是A[n+1]: (1)第一趟排序是在无序区A[1]到A[n]中选出最小的记录,将它与A[1]交换,确定最小值; (2)第二趟排序是在A[2]到A[n]中选关键字最小的记录,将它与A[2]交换,确定次小值; (3)第i趟排序是在A[i]到A[n]中选关键字最小的记录,将它与A[i]交换; (4)共n-1趟排序。

9.4.1 简单选择排序 算 法 void SelectSort(SqList &L) {int i,j,low; for(i=1;i<L.length;i++) {low=i; for(j=i+1;j<=L.length;j++) if(L.r[j].key<L.r[low].key) low=j; if(i!=low) {L.r[0]=L.r[i];L.r[i]=L.r[low];L.r[low]=L.r[0]; }

9.4.1 简单选择排序 算法分析 4. 算法分析 (1)稳定性 简单选择排序方法是稳定的。 (2)时间复杂度 比较O(n2),移动最好O(1),最差O(n) (3)空间复杂度 为O(1)。

9.4.2 树形选择排序 引入 树形选择排序,又称锦标赛排序:按锦标赛的思想进行排序,目的是减少选择排序中的重复比较次数。 例如: 4,3,1,2 在选择排序中3和4的比较次数共发生了三次。

9.4.2 树形选择排序 示例演示 6 6 8 9 6 17 8 6 10 9 20 8 9 90 17 输出6

9.4.2 树形选择排序 示例演示 8 9 8 9 20 17 8  10 9 20 8 9 90 17 输出8

9.4.2 树形选择排序 算法分析 (1)稳定性 树形选择排序方法是稳定的。 (2)时间复杂度 比较O(nlog2n) (3)空间复杂度 为O(n)。

9.4.3 堆排序 引 入 堆排序属于选择排序:出发点是利用前一次比较的结果,减少“比较”的次数。

9.4.3 堆排序 堆的定义 n个元素的序列A[1].key,A[2].key,…,A[n].key,当且仅当满足下述关系时,称之为堆。 A[i].key≤A[2*i].key 且 A[i].key≤A[2*i+1].key A[i].key≥A[2*i].key A[i].key≥A[2*i+1].key 小根堆 大根堆

9.4.3 堆排序 小根堆例子 0 1 2 3 4 5 6 7 8 12 22 34 40 30 36 50 41 12 22 34 40 30 36 50 41 小根(顶)堆

9.4.3 堆排序 大根堆例子 0 1 2 3 4 5 6 7 8 87 50 36 40 30 34 12 22 87 50 36 40 30 34 12 22 大根(顶)堆

9.4.3 堆排序 利用大根堆进行排序的示例演示 87 87 50 36 40 30 34 12 22 50 36 22 50 36 40 30 34 12 87 40 30 34 12 22 22 50 36 40 30 34 12 87

9.4.3 堆排序 堆排序的思想 堆排序需解决两个问题: (1) 由一个无序序列建成一个堆。 (2) 在输出堆顶元素之后,调整剩余元素成为一个新的堆。

9.4.3 堆排序 堆排序的算法(采用大根堆) (1) 按关键字建立A[1],A[2],…A[n]的大根堆; (2) 输出堆顶元素,采用堆顶元素A[1]与最后一个元素A[n]交换,最大元素得到正确的排序位置; (3) 此时前n-1个元素不再满足堆的特性,需重建堆; (4) 循环执行b,c两步,到排序完成。

9.4.3 堆排序 算法示例演示 例 对无序序列{50,38,48,97,49,13,27,65}进行堆排序。 (1)先建一个完全二叉树: 50 2)从最后一个非终端结点开始建堆; n个结点,最后一个非终端结点的下标是n/2 38 48 97 49 13 27 65

9.4.3 堆排序 算法示例演示 50 50 38 48 97 48 97 49 13 27 38 49 13 27 65 50 65 97 97 48 65 48 65 49 13 27 50 49 13 27 38 38

9.4.3 堆排序 算法示例演示 50 s 78 38 49 j s j 75 78 65 64 63 62 m j

9.4.3 堆排序 筛选算法 void HeapAdjust(HeapType &H, int s, int m) {int j; RedType rc; rc = H.r[s]; for (j=2*s; j<=m; j*=2) {if (j<m && H.r[j].key<H.r[j+1].key) ++j; if (rc.key >= H.r[j].key) break; H.r[s] = H.r[j]; s = j; } H.r[s] = rc; // 插入 } // HeapAdjust

9.4.3 堆排序 建堆算法代码 for (i=H.length/2; i>0; --i) HeapAdjust ( H, i, H.length );

9.4.3 堆排序 堆排序算法代码 void HeapSort(HeapType &H) { int i; RcdType temp; for (i=H.length/2; i>0; --i) HeapAdjust ( H, i, H.length ); for (i=H.length; i>1; --i) { temp=H.r[i];H.r[i]=H.r[1]; H.r[1]=temp; HeapAdjust(H, 1, i-1); } } // HeapSort

9.4.3 堆排序 算法分析 (1)堆排序是不稳定的排序。 (2)时间复杂度为O(nlog2n)。 最坏情况下时间复杂度为O(nlog2n)的算法。 (3)空间复杂度为O(1)。 {2,38,38} 38 2 38 2 38 38 38 2 38

第9章 内部排序 9.1 概述 9.2 插入排序 9.3 快速排序 9.4 选择排序 9.5 归并排序 9.6 基数排序 9.1 概述 9.2 插入排序 9.3 快速排序 9.4 选择排序 9.5 归并排序 9.6 基数排序 9.7 内部排序方法的比较

9.5 归并排序 归并的定义 又叫合并,两个或两个以上的有序序列合并成一个有序序列。

for (j=m+1, k=i; i<=m && j<=n; ++k) { if LQ(SR[i].key,SR[j].key) 9.5 归并排序 归并示例演示 i m n SR[] 08 21 25 49 62 72 93 16 22 23 j i i j j j i for (j=m+1, k=i; i<=m && j<=n; ++k) { if LQ(SR[i].key,SR[j].key) TR[k] = SR[i++]; else TR[k] = SR[j++]; } i n TR[] 08 16 21 22 23 25 25 49 62 72 93 k k k k k

while (k<=n && i<=m) TR[k++]=SR[i++]; if (j<=n) 9.5 归并排序 归并示例演示 i m n SR[] 08 21 25 49 62 72 93 16 22 23 j i i j j j i if (i<=m) while (k<=n && i<=m) TR[k++]=SR[i++]; if (j<=n) while (k<=n &&j <=n) TR[k++]=SR[j++]; i n TR[] 08 16 21 22 23 25 25 49 62 72 93 k k k k k

9.5 归并排序 归并算法 void Merge (RcdType SR[], RcdType TR[], int i, int m, int n) { int j,k; ……………………….. } // Merge

9.5 归并排序 归并算法 for (j=m+1, k=i; i<=m && j<=n; ++k) { if LQ(SR[i].key,SR[j].key) TR[k] = SR[i++]; else TR[k] = SR[j++]; } if (i<=m) while (k<=n && i<=m) TR[k++]=SR[i++]; if (j<=n) while (k<=n &&j <=n) TR[k++]=SR[j++];

给定排序码25,57,48,37,12,92,86,写出二路归并排序过程。 9.5 归并排序 2-路归并排序方法示例 例 给定排序码25,57,48,37,12,92,86,写出二路归并排序过程。 A[] 25 57 48 37 12 92 86 B[] 25 57 37 48 12 92 86 一趟 A[] 25 37 48 57 12 86 92 二趟 B[] 12 25 37 48 57 86 92 三趟

9.5 归并排序 2-路归并排序方法思想 (1) 将n个记录看成是n个长度为1的有序子表; (2) 将两两相邻的有序子表进行归并,若子表数为奇数,则留下的一个子表直接进入下一次归并; (3) 重复步骤(2),直到归并成一个长度为n的有序表。

void Msort(RcdType A[],RcdType B[],int n, int l) {int i=1,t; 9.5 归并排序 2-路归并排序核心算法 void Msort(RcdType A[],RcdType B[],int n, int l) {int i=1,t; while (i+2*l-1<=n); {Merge (A,B,i,i+l-1,i+2*l-1) i=i+2*l; } …………………… R[] … i=1 l 2*l i+2l-1 i i+l-1

void Msort(RcdType A[],RcdType B[],int n, int l) {…………. 9.5 归并排序 2-路归并排序核心算法 void Msort(RcdType A[],RcdType B[],int n, int l) {…………. if (i+l-1<n) Merge(A,B,i,i+l-1,n); else for (t=i;t<=n;t++) B[t]=A[t]; } n … i+l-1 i+2l-1 i

9.5 归并排序 2-路归并排序算法 void MergeSort(RcdType A[],int n) {int l=1; Rcdtype B[]; while (l<n) {mpass(A,B,n,l) l=2*l; mpass(B,A,n,l); }

9.5 归并排序 2-路归并排序算法分析 (1) 稳定性 归并排序是稳定的排序方法。 (2) 时间复杂度 每趟归并所花时间比较移动都是O(n); 归并趟数为log2n; 时间复杂度为O(nlog2n)。 (3) 空间复杂度是O(n)。

第9章 内部排序 9.1 概述 9.2 插入排序 9.3 快速排序 9.4 选择排序 9.5 归并排序 9.6 基数排序 9.1 概述 9.2 插入排序 9.3 快速排序 9.4 选择排序 9.5 归并排序 9.6 基数排序 9.7 内部排序方法的比较

9.6.1 顺序基数排序 基数排序的起源 (1)基数起源于排序箱(桶)排序,设置若干个箱子(桶),依次扫描待排序的记录,A[1],A[2],…,A[n],把关键字为k的记录放在第k个箱子里,按序号将非空的箱子里的记录收集起来。 (2)箱(桶)排序的缺点:如果关键字位数太大,这样做空间复杂度和时间复杂度都太大。

9.6.1 顺序基数排序 事例演示 Q[0] 890 210 Q[1] 321 901 Q[2] 432 012 待排序关键字:321 986 123 432 543 018 765 678 987 789 098 890 109 901 210 012 Q[3] 123 543 Q[4] Q[5] 765 Q[6] 986 Q[7] 987 Q[8] 018 678 098 Q[9] 789 109

9.6.1 顺序基数排序 事例演示 Q[0] 901 109 Q[1] 210 012 018 Q[2] 321 123 890 210 321 901 432 012 123 543 765 986 987 018 678 098 789 109 Q[3] 432 Q[4] 543 Q[5] Q[6] 765 Q[7] 678 Q[8] 986 987 789 Q[9] 890 098

9.6.1 顺序基数排序 事例演示 Q[0] 012 018 098 Q[1] 109 123 Q[2] 210 Q[3] 321 901 109 210 012 018 123 543 765 678 986 987 789 809 098 Q[4] 432 Q[5] 543 Q[6] 678 Q[7] 765 789 Q[8] 890 Q[9] 901 986 987

9.6.1 顺序基数排序 排序过程 设待排记录A的关键字是figure位的正整数。 (1) 从最低位(个位)开始,扫描关键字的pass位,把等于0的插入Q[0],…,等于9的插入Q[9]。 (2) 将Q[0],…,Q[9]中的数据依次收集到A[]中。 (3) pass+1直到figure,重复执行1,2两步

return((k/pow10(p-1))%10); } 9.6.1 顺序基数排序 求关键字k的第p位算法 int RADIX(int k,int p) { return((k/pow10(p-1))%10); }

9.6.1 顺序基数排序 基数排序算法 void radixsort(int figure, QUEUE &A){ QUEUE Q[10];records data; int pass,r,i; //pass用于位数循环,r取位数 for(pass=1;pass<=figure;pass++) 把10个队列置空 while(!EMPTY(A)) { 取A中元素dada, 计算data的关键字的第pass位的值r, 放入队列Q[r]中; } 把10个队列中的值依次收集到A中 }

9.6.1 顺序基数排序 基数排序算法 void radixsort(int figure,QUEUE &A){ QUEUE Q[10];records data; int pass,r,i; //pass用于位数循环,r取位数 for(pass=1;pass<=firure;pass++){ for(i=0;i<=9;i++) MAKENULL(Q[i]) while(!EMPTY(A)) { data=FRONT(A); DEQUEUE(A); r=RADIX(data.key,pass); ENQUEUE(data,Q[r]); }

9.6.1 顺序基数排序 基数排序算法 For(i=0;i<=9;i++) While(!EMPTY(Q[i])) {data=FRONT(Q[i]); DEQUEUE(Q[i]); ENQUEUE(data,A); }

9.6.1 顺序基数排序 问题分析 如果采用顺序队列,队列的长度怎么确定? 110 920 230 030 090 320 100 400 503 765 678 986 987 789 890 098 如果采用数组表示队列,队列的长度很难确定,太大造成浪费,小了会产生溢出。 一般采用链队列.

9.6.2 链式基数排序 存储结构 struct celltype{ records element; celltype *next } struct QUEUE{ celltype *front; celltype *rear; }

9.6.2 链式基数排序 事例演示 Q0 012 018 098 ^ Q1 109 123 ^ Q2 210

9.6.2 链式基数排序 收集算法关键语句 void CONCATENATE(QUEUE &Q[0], QUEUE &Q[1]){ if(!EMPTY(Q[1])){ Q[0].rear->next=Q[1].front->next; Q[0].rear=Q[1].rear; }

9.6.2 链式基数排序 两种收集算法的比较 For(i=0;i<=9;i++) While(!EMPTY(Q[i])) {data=FRONT(Q[i]); DEQUEUE(Q[i]); ENQUEUE(data,A); } 顺序收集算法 for(i=1;i<=9;i++) CONCATENATE(Q[0],Q[i]); A=Q[0]; 链式收集算法

9.6.2 链式基数排序 算法分析 基数排序是稳定的 时间复杂性与空间复杂性分析: 设关键字位数为d 则时间复杂性为O(dn) 考虑到d是一个常数 时间复杂性为O(n) 空间复杂性O(n)

第9章 内部排序 9.1 概述 9.2 插入排序 9.3 快速排序 9.4 选择排序 9.5 归并排序 9.6 基数排序 9.1 概述 9.2 插入排序 9.3 快速排序 9.4 选择排序 9.5 归并排序 9.6 基数排序 9.7 内部排序方法的比较

9.7 内部排序方法的比较 n n2 n2 n n2 n2 n2 n2 n n n2 √ 1 √ 1 nlog2n × log2n 1 √ 比较次数 移动次数 稳定 性 附加存储 最好 最差 直接插入排序 冒泡排序 快速排序 简单选择排序 堆排序 归并排序 基数排序 n n2 n2 √ 1 n n2 n2 √ 1 nlog2n n2 n2 × log2n n n n2 1 √ nlog2n nlog2n 1 × nlog2n nlog2n √ n dn …… √ n

本章小结 熟练掌握:直接插入排序、希尔排序、冒泡排序、快速排序、简单选择排序、堆排序、归并排序、基数排序的思想和算法。充分了解各种排序算法的应用背景和优缺点。 加强各种排序算法在实际应用中的训练,提高实际应用水平。