C语言常见排序算法ppt课件.ppt
上章回顾上章回顾二叉树的定义树深度的定义什么样的二叉树是满二叉树中序遍历的规则常见排序算法常见排序算法第六章第六章预习检查预习检查课程目标课程目标本章概述本章概述几种常见排序算法。几种常见排序算法。 本章目标本章目标熟悉常见的查找算法和排序算法熟悉常见的查找算法和排序算法难点难点快速排序算法快速排序算法 本章结构本章结构数据结构与算法初步数据结构与算法初步常见的排序算法6.1 常见的排序算法常见的排序算法 冒泡排序 快速排序直接插入排序 希尔排序 选择排序 堆排序归并排序 6.1.1 冒泡排序冒泡排序算法描述设待排序记录序列中的记录个数为设待排序记录序列中的记录个数为n n一般地,第一般地,第i i趟起泡排序从趟起泡排序从1 1到到n-i+1n-i+1依次比较相邻两个记录的关键字,如果发生逆序,则交换之依次比较相邻两个记录的关键字,如果发生逆序,则交换之其结果是这其结果是这n-i+1n-i+1个记录中,关键字最大的记录被交换到第个记录中,关键字最大的记录被交换到第n-i+1n-i+1的位的位置上,最多作置上,最多作n-1n-1趟趟。6.1.1 冒泡排序冒泡排序算法实例0 1 2 3 4 56.1.1 冒泡排序冒泡排序算法实例0 1 2 3 4 56.1.1 冒泡排序冒泡排序算法实例初始关键字第一趟排序第四趟排序第二趟排序第三趟排序第五趟排序6.1.1 冒泡排序冒泡排序算法实现输入n 个数给a1 到 anfor j=1 to n-1for i=1 to n-jaiai+1真假aiai+1输出a1 到 an#include main() int a11,i,j,t; printf(Input 10 numbers:n); for(i=1;i11;i+) scanf(%d,&ai); printf(n); for(j=1;j=9;j+) for(i=1;iai+1) t=ai; ai=ai+1; ai+1=t; printf(The sorted numbers:n); for(i=1;i11;i+)printf(%d ,ai);6.1.2 快速排序快速排序 算法特点:快速排序是通过比较关键码、交换记录,快速排序是通过比较关键码、交换记录,以某个记录为界以某个记录为界(该记录称为支点该记录称为支点),将待排序列分成两部分,将待排序列分成两部分一部分所有记录的关键码大于等于支点记录的关键码一部分所有记录的关键码大于等于支点记录的关键码另一部分所有记录的关键码小于支点记录的关键码另一部分所有记录的关键码小于支点记录的关键码 6.1.2 快速排序快速排序 算法描述:任取待排序记录序列中的某个记录任取待排序记录序列中的某个记录( (例如取第一个记录例如取第一个记录) )作为基准作为基准( (枢枢),),按照该记录的按照该记录的关键字大小关键字大小, ,将整个记录序列划分为左右两个子序列将整个记录序列划分为左右两个子序列左侧子序列中所有记录的关键字都小于或等于基准记录的关键字左侧子序列中所有记录的关键字都小于或等于基准记录的关键字 右侧子序列中所有记录的关键字都大于基准记录的关键字右侧子序列中所有记录的关键字都大于基准记录的关键字基准记录则排在这基准记录则排在这两个子序列中间两个子序列中间( (这也是该记录这也是该记录最终应安放的位置最终应安放的位置) )。然后分别对这两个子序列重复施行上述方法,直到所有的记录都排在相应位置上为然后分别对这两个子序列重复施行上述方法,直到所有的记录都排在相应位置上为止。止。基准记录也称为枢轴(或支点)记录。基准记录也称为枢轴(或支点)记录。取序列第一个记录为枢轴记录,其关键字为取序列第一个记录为枢轴记录,其关键字为PivotkeyPivotkey指针指针lowlow指向序列第一个记录位置指向序列第一个记录位置指针指针highhigh指向序列最后一个记录位置指向序列最后一个记录位置6.1.2 快速排序快速排序 算法实例:始关键字始关键字pivotkey一次交换一次交换二次交换二次交换三次交换三次交换high-1完成一趟排序完成一趟排序lowhighlowlowlowlowlowhighhighhighhighhigh6.1.2 快速排序快速排序 算法实例:15完成一趟排序完成一趟排序分别进行快速排序分别进行快速排序有序序列有序序列6.1.2 快速排序快速排序 算法分析:快速排序是一个递归过程快速排序是一个递归过程;利用序列第一个记录作为基准,将整个序列划分为左右两个子序列。只要利用序列第一个记录作为基准,将整个序列划分为左右两个子序列。只要是关键字小于基准记录关键字的记录都移到序列左侧;是关键字小于基准记录关键字的记录都移到序列左侧;快速排序的趟数取决于递归树的高度。快速排序的趟数取决于递归树的高度。如果每次划分对一个记录定位后如果每次划分对一个记录定位后, 该记录的左侧子序列与右侧子序列的长该记录的左侧子序列与右侧子序列的长度相同度相同, 则下一步将是对两个长度减半的子序列进行排序则下一步将是对两个长度减半的子序列进行排序, 这是最理想的情这是最理想的情况况 166.1.3 直接插入排序直接插入排序 算法描述:记录存放在数组记录存放在数组R0.n-1中,排序过程的某一中间时刻,中,排序过程的某一中间时刻,R被划分被划分成两个子区间成两个子区间R0i-1和和Ri.n-1,其中:前一个子区间是已排好,其中:前一个子区间是已排好序的有序区;后一个子区间则是当前未排序的部分。序的有序区;后一个子区间则是当前未排序的部分。基本操作将当前无序区的第将当前无序区的第1个记录个记录Ri插入到有序区插入到有序区R0.i-1中适当的位置中适当的位置,使,使R0i变为新的有序区变为新的有序区 6.1.3 直接插入排序直接插入排序 操作细节:当插入第当插入第i(i1)i(i1)个对象时个对象时, , 前面的前面的r0, r1, r0, r1, , ri-1, ri-1已经排已经排好序。好序。用用riri的关键字与的关键字与ri-1, ri-2, ri-1, ri-2, 的关键字顺序进行比较的关键字顺序进行比较( (和顺和顺序查找类似序查找类似) ),如果小于,则将,如果小于,则将rxrx向后移动向后移动( (插入位置后的记录向插入位置后的记录向后顺移后顺移) )找到插入位置即将找到插入位置即将riri插入插入6.1.3 直接插入排序直接插入排序 实用例子:已知待序的一组记录的初始排列为:已知待序的一组记录的初始排列为:21, 25, 49, 2521, 25, 49, 25* *, 16, 08, 16, 080 1 2 3 4 56.1.3 直接插入排序直接插入排序 实用例子:0 1 2 3 4 5 temp2525250 1 2 3 4 5 temp494949252525* * *0 1 2 3 4 56.1.3 直接插入排序直接插入排序 实用例子:0 1 2 3 4 5 temp1616160 1 2 3 4 5 temp0808080 1 2 3 4 5完成6.1.3 直接插入排序直接插入排序 算法实现:void InsertSort (int r , int n ) / 假设关键字为整型,放在向量假设关键字为整型,放在向量r中中 int i, j, temp; for (i = 1;i0;j- -) /从后向前顺序比较,并依次后移从后向前顺序比较,并依次后移 if ( temp rj-1 ) rj = rj-1; else break; rj = temp; 6.1.3 直接插入排序直接插入排序 算法分析:关键字比较次数和记录移动次数与记录关键字的初始排列有关。关键字比较次数和记录移动次数与记录关键字的初始排列有关。最好情况下最好情况下, 排序前记录已按关键字从小到大有序排序前记录已按关键字从小到大有序, 每趟只需与前面有每趟只需与前面有序记录序列的最后一个记录比较序记录序列的最后一个记录比较1次次, 移动移动2次记录次记录, 总的关键字比较次总的关键字比较次数为数为 n-1, 记录移动次数为记录移动次数为 2(n-1)在平均情况下的关键字比较次数和记在平均情况下的关键字比较次数和记录移动次数约为录移动次数约为n2/4 。直接插入排序是一种稳定的排序方法直接插入排序是一种稳定的排序方法直接插入排序最大的优点是简单,在记录数较少时,是比较好的办法直接插入排序最大的优点是简单,在记录数较少时,是比较好的办法6.1.4 希尔排序希尔排序 希尔排序又称缩小增量排序是1959年由D.L.Shell提出来的 算法描述先取定一个小于先取定一个小于n的整数的整数d作为第一个增量,把表的全部记录分成作为第一个增量,把表的全部记录分成d组组所有距离为所有距离为d1的倍数的记录放在同一组中,在各组内进行直接插入的倍数的记录放在同一组中,在各组内进行直接插入排序排序然后取第二个增量然后取第二个增量d2d1重复上述的分组和排序,直至增量重复上述的分组和排序,直至增量d1,即所有记录放在同一组中,即所有记录放在同一组中进行直接插入排序为止。进行直接插入排序为止。 6.1.4 希尔排序希尔排序 算法特点先取定一个小于先取定一个小于n的整数的整数d作为第一个增量,把表的全部记录分成作为第一个增量,把表的全部记录分成d组组所有距离为所有距离为d1的倍数的记录放在同一组中,在各组内进行直接插入的倍数的记录放在同一组中,在各组内进行直接插入排序排序然后取第二个增量然后取第二个增量d2d1重复上述的分组和排序,直至增量重复上述的分组和排序,直至增量d1,即所有记录放在同一组中,即所有记录放在同一组中进行直接插入排序为止。进行直接插入排序为止。 6.1.4 希尔排序希尔排序 运用实例先取定一个小于先取定一个小于n的整数的整数d作为第一个增量,把表的全部记录分成作为第一个增量,把表的全部记录分成d组组所有距离为所有距离为d1的倍数的记录放在同一组中,在各组内进行直接插入的倍数的记录放在同一组中,在各组内进行直接插入排序排序然后取第二个增量然后取第二个增量d2d1重复上述的分组和排序,直至增量重复上述的分组和排序,直至增量d1,即所有记录放在同一组中,即所有记录放在同一组中进行直接插入排序为止。进行直接插入排序为止。 6.1.4 希尔排序希尔排序 算法描述首先取一个整数首先取一个整数 gap n(gap n(待排序记录数待排序记录数) ) 作为间隔作为间隔, , 将全部记录分为将全部记录分为 gap gap 个子序列个子序列, , 所有距离为所有距离为 gap gap 的记录放在同一个子序列中的记录放在同一个子序列中在每一个子序列中分别施行直接插入排序。在每一个子序列中分别施行直接插入排序。然后缩小间隔然后缩小间隔 gap, gap, 例如取例如取 gap = gap/2gap = gap/2重复上述的子序列划分和排序工作,直到最后取重复上述的子序列划分和排序工作,直到最后取gap = 1, gap = 1, 将所有记录放在将所有记录放在同一个序列中排序为止。同一个序列中排序为止。6.1.4 希尔排序希尔排序 运用实例已知待排序的一组记录的初始排列为:已知待排序的一组记录的初始排列为:21, 25, 49, 2521, 25, 49, 25* *, 16, 08, 16, 080 1 2 3 4 5 6.1.4 希尔排序希尔排序 运用实例T= 30 1 2 3 4 50 1 2 3 4 5T= 2T= 16.1.4 希尔排序希尔排序 算法分析开始时开始时 gap gap 的值较大的值较大, , 子序列中的记录较少子序列中的记录较少, , 排序速度较快排序速度较快随着排序进展随着排序进展, , gap gap 值逐渐变小值逐渐变小, , 子序列中记录个数逐渐变多子序列中记录个数逐渐变多, ,由于由于前面大多数记录已基本有序前面大多数记录已基本有序, , 所以排序速度仍然很快所以排序速度仍然很快GapGap的取法有多种。的取法有多种。 shell shell 提出取提出取 gap = gap = n/2n/2 ,gap = gap = gap/2gap/2 ,直到直到gap = 1gap = 1。6.1.5 选择排序选择排序 排序过程:排序过程:首先通过首先通过n-1次比较,从次比较,从n个数中找出最小的,个数中找出最小的, 将它与第一个数将它与第一个数 交换交换第一趟选择排序,结果最小的数被安置在第一个元素位第一趟选择排序,结果最小的数被安置在第一个元素位置上置上再通过再通过n-2次比较,从剩余的次比较,从剩余的n-1个数中找出关键字次小的记录,个数中找出关键字次小的记录,将它与第二个数交换将它与第二个数交换第二趟选择排序第二趟选择排序重复上述过程,共经过重复上述过程,共经过n-1趟排序后,排序结束趟排序后,排序结束6.1.5 选择排序选择排序 排序实例:排序实例:例初始: 49 38 65 97 76 13 27 kji=11349一趟: 13 38 65 97 76 49 27 i=22738二趟: 13 27 65 97 76 49 38 三趟: 13 27 38 97 76 49 65 四趟: 13 27 38 49 76 97 65 五趟: 13 27 38 49 65 97 76 六趟: 13 27 38 49 65 76 97 kkkkjjjjjjjjjj6.1.5 选择排序选择排序 算法实例:算法实例:0 1 2 3 4 56.1.5 选择排序选择排序 算法实例:算法实例:0 1 2 3 4 5最小者最小者最小者最小者各趟排序后的结果各趟排序后的结果6.1.5 选择排序选择排序 算法实例:算法实例:0 1 2 3 4 5i =2时选择排序的过程时选择排序的过程i k j i k j i k j 6.1.5 选择排序选择排序 算法实例:算法实例:0 1 2 3 4 5i k j 6.1.5 选择排序选择排序 算法实现:算法实现:输入n 个数给a1 到 anfor i=1 to n-1for j=i+1 to najak真假k=j输出a1 到 ank=iaiaki != k真假#include main() int a11,i,j,k,x; printf(Input 10 numbers:n); for(i=1;i11;i+) scanf(%d,&ai); printf(n); for(i=1;i10;i+) k=i; for(j=i+1;j=10;j+) if(ajak) k=j; if(i!=k) x=ai; ai=ak; ak=x; printf(The sorted numbers:n); for(i=1;i11;i+)printf(%d ,ai);各种排序算法对比分析各种排序算法对比分析排序法 平均时间 最差情形 稳定度 额外空间 备注 冒泡 O(n2) O(n2) 稳定 O(1) n小时较好 交换 O(n2) O(n2) 不稳定 O(1) n小时较好 选择 O(n2) O(n2) 不稳定 O(1) n小时较好 插入 O(n2) O(n2) 稳定 O(1) 大部分已排序时较好 基数 O(logRB) O(logRB) 稳定 O(n) B是真数(0-9),R(个十百) Shell O(nlogn) O(ns) 1s2 不稳定 O(1) s是所选分组 快速 O(nlogn) O(n2) 不稳定 O(nlogn) n大时较好 归并 O(nlogn) O(nlogn) 稳定 O(1) n大时较好 堆 O(nlogn) O(nlogn) 不稳定 O(1) n大时较好 阶段小节阶段小节 几种常见的排序算法 冒泡排序的特点 快速排序的特点,一趟排序的子过程本章总结本章总结数据结构与算法初步数据结构与算法初步常见的排序算法重点讲述重点讲述冒泡排序和快速排序的特,同时大概了解直接插入排序,希尔排序和选择排序的基本思路实验实验1题目题目:实现对数组265,301,751,129,937,863,742,694,076,438进行排序,用快速排序方法来实现。并列出每趟排序的结果实验目的实验目的考察快速排序算法的基本思路 了解快速排序算法的每趟操作流程 实验分析实验分析建立一个数组,并初始化进行数据的第一趟快速排序 了解快速排序每趟操作结果,分析排序快速的最快数组类型和最慢数组类型