本文为笔者学习排序算法时整理的学习笔记,包括刷过的练习题目。文中部分题解与图片摘自“牛客网”。因为知识点众多,后续会持续整理更新~
期望运行时间复杂度也就是平均时间复杂度。
选择适合的排序算法时,需要
考虑表中元素的个数。
排序算法中的比较次数
与初始元素序列的排列
无关❌。【只有选择排序
和基数排序
无关,其余都有关】
交换类
:快排,冒泡
插入类
:希尔,直接插入
选择
:堆排序,简单选择
归并类
:二路/多路归并
对于排序算法,经常关注的是其时间复杂度和稳定性。下列排序算法中平均时间复杂度是O(nlogn)且稳定的是归并排序
。
桶
排序)学,快(快
速排序)些(希
尔排序)选(选
择排序)堆(堆
排序)人。桶
)计(基
数排序)个数;快
速排序)些归(归
并排序)队(堆
排序);选择
排序)相貌(冒
泡排序)好的直接插入(直接插入
排序)比赛;平均情况、最好情况和最坏情况下的时间复杂度都为O(n²)的是:直接选择排序
。
内部排序方法的稳定性是指该排序算法不允许有相同的关键字记录。❌
排序方法的稳定性是指在排序过程中是否改变相同元素的相对位置,若不变则稳定,否则不稳定。
影响时间复杂度的主要因素为比较的次数。
对n个数字进行排序,期中两两不同的数字的个数为k,n远远大于k,而n的取值区间长度超过了内存的大小,时间复杂度最小可以是O(nlogk)
。
精俭排序,即一对数字不进行两次和两次以上的比较,以下是“精俭排序”的是插入排序
、归并排序
。
设一组初始关键字记录关键字为(19,15,12,18,21,36,45,10),则以19位基准记录的一趟快速排序结束后的结果为(10,15,12,18,19,36,45,21
)
对长度为n的线性表排序,在最坏情况下,比较次数不是n(n-1)/2的排序方法是( 堆排序
)。
对长度为n的线性表排序,在最坏情况下,比较次数是n(n-1)/2的排序方法是快速排序
、冒泡排序
、直接插入排序
。
下列排序法中,元素的交换可能会出现新的逆序的排序方式是(快速排序
)。
产生新的逆序对,并不是说逆序对的数目发生改变。稳定的排序算法,每交换一次,逆序对的数目必然发生改变。
冒泡每交换一次,会减少一个逆序对,并不会产生新的逆序对。
简单插入排序,若插入到已排序序列的最后,则不会产生新的逆序对。
简单选择排序,每次将一个元素归位。无论由小到大归位,还是由大到小归位,都不会产生新的逆序对。
而快排,是跳跃式交换,必然会产生新的逆序对。
0~999999之间的所有数字中,任何一位都不包括数字3的数字的总数为472392
。
首位不能为0和3,其余不能为3:89999*9。尾数是2。
将两个各有n个元素的有序表归并成一个有序表,最少的比较次数是(n
)
基本有序的情况下:快排最慢,堆排最快。
堆排序最坏情况下比较次数为 O(nlog2n) ,快速排序、简单插入排序、冒泡排序最坏情况下比较次数为 n(n-1)/2 。
尔排序和堆排序都利用了顺序存储的随机访问特性,而链式存储不支持这种性质,所以时间复杂度会增加。
现有N条词以及对应的拼音串,对其排序,排序规则:首先按拼音串的字母序排序,如果拼音串相同,则按当前词所在的顺序排序,下列哪些排序算法符合条件?插入排序
、冒泡排序
。
按当前词所在顺序排序即排序算法要稳定。
选择排序,快速排序,希尔排序,堆排序 都不稳定
冒泡排序,插入排序,归并排序,基数排序 都稳定
排序
)。
A:可以枚举起点和终点然后对子数组求和,最后输出最大值,正确
B:最大连续和的子数组要么在左半区间,要么在右半区间,要么就是横跨了两个区间,可以分治,正确
C:设dp[i]表示以第i号元素结尾的最大连续和,最后输出dp数组中的最大值,正确
D:求的是数组的最大连续和,数字的顺序不能变,排序后改变了元素的顺序,错误
O(mn(logm))
)稳定
排序算法之基数排序
元素的移动次数与关键字的初始排列次序无关
的是基数排序
。
用基数排序需要进行(最大元素的长度
)趟的分配和回收才能使得初始关键字序列变成有序序列。【个位、十位、百位……】
对[21, 49, 84, 45, 12]进行基数排序,第一趟排序的结果为:([21, 12, 84, 45, 49]
)。
对给定的关键字序列110, 119, 007, 911, 114, 120, 122 进行基数排序, 则第 2 趟分配收集后得到的关键字序列是(007, 110, 911, 114, 119, 120, 122
)。
稳定
merge sort排序算法之归并排序
一趟排序结束都至少能够确定一个元素最终位置
❌【二路归并排序每趟对子表进行两两归并从而得到若干个局部有序的结果,但无法确定最终位置。】
归并排序需要一个跟原始数组同样大小的空间做归并操作。归并排序和基数排序所需辅助空间最多,为O(n)
就排序算法平均所用的辅助空间
而言,堆排序、快速排序、归并排序的大小关系是堆排序<快速排序<归并排序
。【归并排序需要的附加存储开销最大】
归并排序法的最好时间复杂度
和此情况下的空间复杂度
分别是O(nlogn)
和O(n)
。【归并排序不会退化 无论初始条件什么情况时间复杂度都是0(nlogn)【最坏时间复杂度O(nlogn)
】】
外部排序常用的算法是多路归并排序
。
归并排序使用了分治
策略的思想。
在内部排序时,若选择了归并排序而没有选择插入排序,则可能的理由是归并排序的运行效率更高
。
对10TB的数据文件进行排序,应使用的方法是归并排序
。
外部排序指待排序文件较大,内存一次性放不下,需存放在外部介质中。
外部排序通常采用归并排序法
。
希尔排序、堆排序、快速排序都是内部排序的方法。
归并排序
算法在输入数据逆序
情况下排序速度最快。
假设你只有100MB的内存,需要对1GB的数据进行排序,最合适的算法是多路归并排序
。
将N条长度均为M的有序链表进行合并,合并以后的链表也保持有序,时间复杂度为O(N * M * logN)
。
现有1G数据需要排序,计算资源只有1G内存可用,下列排序方法中最可能出现性能问题的是归并排序
。
设某文件经内排序后得到100个初始归并段(初始顺串),若使用多路归并排序算法,且要求三趟归并完成排序,问归并路数最少为5
。
设一组初始记录关键字序列为(25,50,15,35,80,85,20,40,36,70),其中含有5个长度为2的有序子表,则用归并排序的方法对该记录关键字序列进行一趟归并后的结果为(15,25,35,50,20,40,80,85,36,70
)。
若外部存储上有3110400个记录,做6路平衡归并排序,计算机内存工作区能容纳400个记录,则排序好所有记录,需要作5
趟归并排序。
每次将工作区装满,共计3110400/400=7776个归并段,对于n路归并排序,m个归并段,需要归并排序的次数为次,代入数据得到答案为5。
对于初始关键字(67,66,77,82,78,51,58),使用二路归并排序
,第一趟归并之后其序列变为66,67,77,82,51,78,58
。
第一趟执行归并的为(67,66),(77,82),(78,51),(58)
序列变为了(66,67),(77,82),(51,78),(58)
即66,67,77,82,51,78,58
不稳定
quick sort排序算法之快速排序
快速排序的基本思想就是选取一个数作为基准【通常选择第一个元素
或后一个元素
】,将数据按照基准数据分为左右两部分,左边都比基准数据小,右边都比基准数据大,按照中间位置,递归左右两侧,直到只有一个数据时,排序完成。【 快速排序使用了分治
的思想】【一趟排序结束都至少能够确定一个元素最终位置
】
快递排序的递归次数与元素的初始排列有关
。如果每一次划分后分区比较平衡,则递归次数少;如果划分后分区不平衡,则递归次数多。快速排序在最坏情况下的时间复杂度为O(n^2)
,时间复杂度均摊是(nlogn)
。只有基准值处于每次的中间位置才是时间复杂度最好的。
快速排序的递归次数与分区处理顺序无关
,即先处理较长的分区或先处理较短的分区都不影响递归次数。【可以形象地把快速排序的递归调用过程用一个二叉树描述,先处理较长或较短分区,可以想象为交换某一递归结点处的左右子树,这并不会影响树中的分支数。】
对关键码序列28,16,32,12,60,2,5,72快速排序(最常用的快速排序,以第一个关键码为基准
),使用挖坑法,从小到大一次划分结果为((5,16,2,12)28(60,32,72)
)。
25,84,21,47,15,27,68,35,20
进行排序时,变化为:
20,15,21,25,47,27,68,35,84
,
15,20,21,25,35,27,47,68,84
,
15,20,21,25,27,35,47,68,84
的排序方法是(快速排序
)
能说明快速排序是不稳定的排序方法的一组关键字序列是((20, 20,30,10,40)
)
所谓的排序算法的稳定性是指序列中原本数值相同的元素在排序完成后,相同数值的元素的前后关系不变。所以,
至少要含有相同的元素才可能出现不稳定的情况。
根据快排原理,当比对到10,则10与第一个20交换位置,则相对于第二个20发生了位置变化。所以不稳定。
在待排序的数据表已经为有序时,花费时间反而最多的是快速排序
。快排不适合对基本有序的数据集合进行排序。快排序越是无序效率越高。
有字符序列(Q,H,C,Y,P,A,M,S,R,D,F,X),新序列(F,H,C,D,A,M
,P,S,R,Y,Q,X)是快速排序
算法一趟扫描结果。
在快速排序中,要使最坏情况的空间复杂度为O(log2n )则要对快速排序作( 划分元素为三者取中
)修改。
最优的情况下空间复杂度为:O(log2n) ;
每一次都平分数组的情况,基准数尽量为中间数。
为实现快速排序算法,待排序序列宜采用的存储方式是(顺序存储
)。【顺序存储适用于频繁快速查询】
现有一数列{3, 2, 5, 7, 6, 8},要求按升序排序,下面说法正确的是:快速排序,每次选择最后一个元素作为支点,需要比较12次
。
一组记录的排序码为(46,79,56,38,40,84),一趟排序的结果为(40,38,46,56,79,84),则采用的是(快速)排序算法。
快速排序只能使用递归方式实现❌【也可以使用非递归的方式
】
序列{2,1,4,9,8,10,6,20}是某排序算法第二轮排序的结果,则该算法只能是快速排序
。
原序列为{4,1,2,20,8,10,6,9}
第一趟快速排序:以4为轴值,最后得到 2,1,4
,20,8,10,6,9
第二趟快速排序:以20为轴值,最后得到 2,1,4,9,8,10,6,20
快速排序算法是对一个list排序的最快方法
//这里的list指的是双向链表,因而用两个指针是可以操作的,这样也是比较快速的操作。线性排序(如基数排序、桶排序、计数排序是不适合的 ,元素不能快速移动) 冒泡排序需要大量移动元素,这是得不偿失的。 二分只适合顺序表。
综上:选择快速排序最好
快排的阶段性排序结果的特点是,第i趟完成时,会有i个以上的数出现在它最终将要出现的位置不可能是快速排序第2趟排序结果的是:3,2,5,4,7,6,9
。
堆排序
需要构建堆,所以比较次数多于快速排序
。快速排序比较次数更少。
不稳定
heap sort排序算法之堆排序
堆排序最坏为O(nlogn)
一趟排序结束都至少能够确定一个元素最终位置
【堆排序属于选择排序,每次都将大根堆的根结点与表尾结点交换,确定其最终位置。】
要从1000个数据元素中选五个最小的
,下面排序算法中,那个算法最快?堆排序
将整数数组(7-6-3-5-4-1-2)按照堆排序的方式原地进行升序排列,请问在整个排序过程中,元素3的数组下标发生过2
次改变。
注:粉红色代表已经排好序的,绿色代表交换的节点,砖红色代表没做改动的点。
从图中可以看出来,3在交换4和交换5这两步中,位置都有变化,所以一共是2次
注意交换4这一步,本来交换之后,就是有序的,但是程序还会继续调整,直到所有节点调整完毕。
按整数数组的最大堆定义,每次调整完后根结点的元素与最后个元素交换,继续下次调整,直到所有的结点调整完毕。
原数组为 7 6 3 5 4 1 2 满足最大堆定义,直接交换根节点元素
2 6 3 5 4 1 7,交换完毕
6 5 3 2 4 1 7,调整完毕
1 5 3 2 4 6 7,交换完毕
5 4 3 2 1 6 7,调整完毕
1 4 3 2 5 6 7,交换完毕
4 2 3 1 5 6 7,调整完毕
1 2 3 4 5 6 7,交换完毕,此时虽然已有序,但仍需进行最大堆调整,因为最大堆算法时间复杂度为nlog2n,会进行继续搜索调整
3 2 1 4 5 6 7,调整完毕,移动一次
1 2 3 4 5 6 7,交换完毕,移动两次
2 1 3 4 5 6 7,调整完毕
1 2 3 4 5 6 7,交换完毕
数据表A中有10000个元案,如果仅要求求出其中最大的10个元素,则采用(堆排序
)排序算法最节省时间。
从一个无序数组中挑选出其中前十个最大的元素,在以下的排序方法中最快的方法是堆排序
。
堆排序平均执行的时间复杂度
和需要附加的存储空间复杂度
分别是(O(nlog(n))和O(1)
)。整个构建堆的时间复杂度为O(n)
。
排序的方法有很多种,(堆排序
)法是基于选择排序的一种方法,是完全二叉树
结构的一个重要应用。
将一个从大到小的数组,用以下排序方法排序成从小到大的,(堆排序
)最快。
在用堆排序算法排序时,如果要进行增序排序,则需要建立“大顶堆”。
堆排序在每一趟排序过程中,都会有一个元素被放置在最终位置上。
将整数数组(7-6-3-5-4-1-2)按照堆排序的方式原地进行升序排列,请问在第一轮排序结束之后,数组的顺序是6-5-3-2-4-1-7
。
使用堆排序方法排序(45,78,57,25,41,89),初始堆为89,78,57,25,41,45
。
堆是完全二叉树
,根据父节点和子节点的关系,可以分为大根堆
和小根堆
。
大根堆的父节点比它的所有子节点大,小根堆的父节点比它的所有子节点小。
兄弟节点间不按大小排序。
堆通常用于获取最值。
用堆可以实现优先队列(priority_queue)
堆数据结构可以用数组方式存储。
对一个堆按层次遍历,不一定能得到一个有序序列。
值类型是在堆上分配的。
最大值
。O(log(n))
。无法判断
。n/2
次。{4353,3444,2344,3344,45,646,657}
。
在一个小根堆中,从根结点到某个叶子结点所经路径上的结点构成一个递增有序序列。
删除最小元素的复杂度是o(logn)
查询最小元素的复杂度是o(1)
下标从1开始,在含有n个关键字的小根堆(堆顶元素最小)中,关键字最大的记录有可能存储在[n/2]+2
位置上。
将一个元素插入大小为len的小顶堆中,最多需要移动log(len)
次,最少需要0
次。
已知关键字序列5,8,12,19,28,20,15,22是小根堆(最小堆),插入关键字3,调整后得到的小根堆是(3,5,12,8,28,20,15,22,19
)。
关键码序列K = { 23 , 40, 28, 19, 20, 42 },经过筛选法建堆过程后,得到的最小堆为19,20,28,40,23,42
。
对关键码集合K={22,11,38,68,43,6,10,48},用筛选法创建最小堆时,从关键码(68
)开始调整。
从下往上,从右到左的顺序,从第一个
非叶结点
开始调整。
不稳定
shell sort排序算法之希尔排序
Shell排序,划分子序列做直接插入排序,所以和初始排列有关。
希尔排序是先分组
,然后针对组内采取插入排序
。
3
。不一定
能够选出一个元素放在其最终位置上的是希尔排序
。【希尔排序每次是对划分的子表进行排序,得到局部有序的结果,所以不能保证每一趟排序结束都能确定一个元素的最终位置。】直接插入排序
。15,40,60,20
)。
已知步长为4
排序前:
50 40 95 20
15 70 60 45
排序后:
15 40 60 20
50 70 95 45
稳定
bubble sort排序算法之冒泡排序
冒泡排序的平均时间复杂度为O(n^2)
,最坏时间复杂度为O(n^2)
冒泡排序是相邻两两比较,把最大的顶上去,如果边上两个元素不是最值,肯定不是冒泡排序。
n(n-1)/2
【逆序对的个数n(n-1)/2】对顺序表R{33,22,18,4,30,29,7,16,9,10}起泡排序,第三趟排序后,顺序表中的数据顺序是4,18,22,7,16,9,10,29,30,33
。
对于每趟排序,从前往后遍历,如果当前位置的数比后面相邻位置的数大,则交换两个位置的数。
第一趟后:{22,18,4,30,29,7,16,9,10,33}
第二趟后:{18,4,22,29,7,16,9,10,30,33}
第三趟后:{4,18,22,7,16,9,10,29,30,33}
冒泡排序有一种优化方法,就是在每趟冒泡的时候都检测这次是否有交换元素的顺序,如果没有交换就说明序列是排好序的,下次就不用再冒泡了!所以和初始序列是有关系的
。
设一组初始记录关键字序列(Q,H,C,Y,P,A,M,S,R,D,F,X),则按字母升序的第一趟冒泡排序结束后的结果是(H,C,Q,P,A,M,S,R,D,F,X,Y
)
线性表的长度为10,在最坏情况下,冒泡排序需要比较次数为(45)。
9+8+……+1 = 45。
设有 1000 个基本有序的元素,希望用最快的速度挑选出其中前 10 个最大的元素,最好选用冒泡排序
排序法。【因为只要前十个最大的,而且数据基本有序,所以此时不必要全部排序,用冒泡排序10趟就能将最大的10个上浮到最后面】【取最小的10个元素使用堆排序,取最大的10个元素使用冒泡排序】
排序算法之选择排序
简单选择排序,在待排序的数组中选出最小(或最大)的与第一个位置的数据交换,然后在剩下的待排序数组中重复找出剩余序列的最大(或最小)。关键字比较的次数与记录的初始排列无关
。一趟排序结束都至少能够确定一个元素最终位置
选择排序每扫描一遍数组,只需要一次交换。
在选择排序中,数据已按升序排列
和数据已按升降序排列
俩者花费时间一样。
以下排序中平均时间复杂度最差的是选择排序
。
归并排序
选择排序
希尔排序
堆排序
京东商城plus会员的消费记录金额分别为900,512,613,700,810,若采用选择排序算法对其进行从小到大的排序,第三趟排序结果为:512 613 700 900 810
。
稳定
排序算法之插入排序
通过构建有序序列,对于未排序数据,在已排序序列中从后向前扫描,找到相应的位置并插入的排序算法是插入排序
。
设一组初始记录关键字的长度为8,则最多经过(7
)趟插入排序可以得到有序序列。
在长度为n的顺序表的第i(1≤i≤n+1)个位置上插入一个元素,元素的移动次数为n-i+1
。
对n个元素用插入法建堆的时间复杂度是O(nlog(n))
。
对同一待排序序列分别进行折半插入排序和直接插入排序,两者之间可能的不同之处是元素之间的比较次数
。
和初始排列有关
,适用于待排序数据大部分已排序时
。【在待排序的元素序列基本有序
的前提下,效率最高
。】直接插入排序
)方法进行递增排序时关键字比较次数最少。直接插入排序
排序算法时间复杂度最低。直接插入排序
。下列排序算法中,某一趟结束后未必能选出一个元素放在其最终位置上的是直接插入排序
。
插入排序方法可能出现这种情况:在最后一趟开始之前,所有的元素都不在其最终应在的正确位置上。【最小的元素在最后一个位置时将出现这种情况】
在对一组记录(54,38,96,23,15,72,60,45,83)进行直接插入排序时,当把第7个记录60插入到有序表时,为寻找插入位置需比较(3
)次。
某学生信息表,设一组表示成绩的关键字序列(24,15,32,28,19,10,40)采用直接插入排序时,当插入记录19到有序表时,为找插入位置需比较次数为4
。
对记录(54
,38,96
,23,15,72
,60
,45,83)进行直接插入排序时,当把第八个记录45插入到有序表时,为找到插入位置需比较(5
)次。
由插入排序算法,当要插入第八个元素时,前七个元素已经有序为:
15 23 38 54 60 72 96
第八个记录45从后向前比较到38时,45>38,找到了前八个元素有序应该放的位置,停止循环,从96到38,共比较了5次。
这题直接数前面有几个比它自己大的数然后 +1 就好了
。插入排序从后往前比
。
设有一组初始关键字序列为(30,20,10,25,15,28),则第4趟直接插入排序结束后的结果的是10,15,20,25,30,28
。
对数据序列{ 15,9,7,8,20,-1,4 }进行排序,进行一趟后数据的排序变为{ 9,15,7,8,20,-1,4 } ,则采用的是(直接插入排序
)算法。
插入排序
。插入排序
)‘D’, ’Q’, ‘U’
, ‘I’, ‘A’, ’N’)只能是插入
排序算法两趟排序后的结果。11,12,13
,7,8,9,23,4,5)是采用下列排序方法之一得到的第二趟排序后的结果,则该排序算法只能是(插入排序
)。假设小明用某个排序算法对整数序列(82,45,25,15,21)进行排序。以下为排序过程中序列状态的变化过程:
输入:82 45 25 15 21
第一步:45 82
25 15 21
第二步:25 45 82
15 21
第三步:15 25 45 82
21
······
请问小明用的是什么排序算法?插入排序
>排序算法之计数排序
计数排序的时间复杂度为O(n+k)
计数排序的空间复杂度为 O(k)
计数排序是一种基于 统计 的排序算法