NOIP--基本算法设计--排序
一、概述
排序,顾名思义,是将一些无序的数据按照一定的规则排列成一个有序序列的过程。排序的方法排序算法虽然很少在NOIP的考题中直接出现,但是它经常会是整体算法的一部分。熟练掌握排序算法,并在考场上快速编写,可在解题时为自己赢得更多的时间和分数。
二、1. 知识点梳理:
Ø 简单排序算法
插入排序:顺次枚举整个数列,将数列中的元素插入到当前已排好序的数列中。对于当前插入第i个元素时,前i-1个元素已经排好序,需要查找第i个元素在前i-1个元素的对应位置并插入。时间复杂度为O(N2)。
选择排序:就是每次选择最小(或最大的)值放到第一个,然后对剩余的数进行排序。时间复杂度为O(N2)。
冒泡排序:每次遍历整个数列,比较两个相邻的数的大小,如果与目标顺序不符,就交换。直到没有可以交换的数对为止。时间复杂度为O(N2)。
Ø 优化排序算法
快速排序:思路与分治的思路类似。在待排序序列中任取一个数,作为“标志”。扫描序列中的其他数,将比“标志”小(或大)的数放到它的左面,将其余的数放到它的右面。完成后,“标志”就把序列分成了两部分,一部分的数都比它小(或大),另一部分的数都不比它小(或大)。接下来,对被划分出的两部分分别进行上述操作。快速排序的最差情况下时间复杂度仍为O(N2),但其平均时间复杂度为O(N log N)。一般情况下,选取标志位时,采用随机选取的方法,就可以避免最差情况的发生。
归并排序:思路也与分治的思路类似。数列划分为长度相等或接近的两部分,分别进行排序,再将这两个有序序列合并,生成一个有序的序列。在合并的过程中,由于前后两个序列均有序,每次只要比较两个序列中的最小(或大)值即可。用队列维护两个序列,每次比较队首元素,弹出较小(或大)值,直至一个队列为空,将剩余的数加到原弹出数列后。时间复杂度为O(N log N)。
堆排序:堆排序需要维护一个叫“堆”的数据结构(在数据结构章节会具体讲),依次从堆中弹出最小(或大)值,直至堆为空。弹出序列即为排序结果。时间复杂度为O(N log N)。
二叉树排序:二叉树排序需要维护一个“二叉排序树”的数据结构(在数据结构章节会具体讲)。将元素顺次插入到二叉排序树中,然后中序遍历整个树,即可得到排序结果。无优化的二叉排序树最坏时间复杂度为O(N2),经过平衡优化的二叉排序树最坏时间复杂度为O(N log N)。
Ø 非基于比较的排序
桶排序:与上述基于比较的排序不同,桶排序给了另一种排序思路。桶排序先设计M个桶,根据数据的值进行分配。由于M个桶是按顺序排列的,所以分配元素之后元素也会按顺序排列。一般桶排序适用于数据范围比较小的情况。时间复杂度为O(max(N,M))。其中N为数据数目,M为数据范围(即包含多少种可能数据)。桶排序的思想跟散列表(Hash表)类似,在后续数据结构章节会具体讲解。
基数排序:基数排序是基于桶排序的一种排序算法。其思路是对n个数据(一般为整数)依次按1,2, ... , k-1, k位上的数字进行桶排序。时间复杂度为O(Nk)。其中k为数字的最大位数。
Ø 排序算法的稳定性
当数据中包含相同元素,排序后它们的顺序与原顺序是否一致,即表明了该排序算法是否稳定。
在上述排序算法中,插入排序、选择排序、冒泡排序、归并排序、二叉树排序、桶排序、基数排序是稳定排序;快速排序、堆排序是不稳定排序。
事实上,所有非稳定排序只要将比较函数加强,也可成为稳定排序。即在原数据基础上,再加一个维度,表示原数据中的元素在初始序列中的位置,比较时,优先比较元素大小,当元素大小相同时,比较初始序列大小。
三、重难点分析:
u 基于比较的算法时间复杂度最优为O(N log N),其证明可参看《算法设计与分析》中关于排序复杂度的介绍。
u 虽然快速排序、归并排序、堆排序、二叉排序树等算法时间复杂度均为O(N log N),但是它们的复杂度常数不同。在纯粹排序的情况下,推荐使用快速排序。
u 虽然优化的排序算法时间复杂度比简单排序算法小,但是对于一些规模很小的数据,简单排序反而比优化排序快。
u 排序算法应熟练掌握并快速编写。
四、例题解析:
例题6-1:统计数字(NOIP2007)
【问题描述】某次科研调查时得到了n (n≤200,000) 个自然数,每个数均不超过1.5*109。已知不相同的数不超过10000个,现在需要统计这些自然数各自出现的次数,并按照自然数从小到大的顺序输出统计结果。
【分析】本题看n的上界,单纯使用优化的排序算法基本也没问题。但对于极限数据(相同元素比较多),快速排序有可能超时。但实际上当年的测试数据不包含此类极限数据。
本题的另一个条件是不相同的数不超过10000个,按照这个条件,很容易想到桶排序,但是由于数据范围较大,直接用桶排序不可行。对此,可用两种方式求解。
解法一:散列+排序。由于不相同的数10000个,可构造一个散列,存储有多少种不相同的数,以及每个数出现多少次。然后对这些出现的不同数进行排序,根据每个数出现的次数,生成最终的排序序列。时间复杂度为O(n + c log c)。其中c为不同元素个数。
解法二:二叉树排序。构造并维护一个平衡二叉排序树,每个节点保存其数值与出现次数,最后中序遍历即可。时间复杂度为O(n log c)。其中c为不同元素个数。
NOIP信息学视频地址
视频地址
链接:https://pan.baidu.com/s/1tHo1DFMaDuMZAemNH60dmw
提取码:7jgr