排序(408)

排序

插入排序

直接插入排序:

操作流程:a[1...i-1]有序,a[i..n]无序,选取a[i]插入到前面有序的数组中去,插入到位置k,再将有序的a[k...i]整体向后移动一个位置

空间复杂度:O(1),没有产生额外的空间,原地变化。

时间复杂度:O(n^2),最坏情况下,每一次找到的k值插入的位置为1。即本来是逆序,排正序

稳定性:稳定,插入元素时,从后向前比较再移动,如果当前两个数字相同,插在该数后面,不会改变顺序

适用性:链表,顺序表

折半插入排序

操作流程:和直接插入排序一样,但是在查找插入位置的时候,k值为折半查找找到的。从原来的O(n)->O(log(n))

空间复杂度,时间复杂度,稳定性和直接插入排序相同

适用性:顺序表

希尔排序

操作流程:利用增量d将数组分成若干个子表,对于子表,进行插入排序,d不断缩减,直到1。

空间复杂度:O(1)

时间复杂度:O(n2)最坏,n在某个范围内可达O(n1.3)

稳定性:不稳定,在划分子表的时候,就可能打乱了顺序。

适用性:顺序表。需要随机存取

交换排序

冒泡排序

操作流程:每次比较数,通过swap函数,把后面最小的给浮到最前面。

空间复杂度:O(1)

时间复杂度:O(n^2),可加一个bool判断,如果当前是有序的情况下,bool为真,说明有序,退出循环

稳定性:稳定,两个数相同不会换位置

适用性:顺序表,链表。

快速排序

重要的算法之一

操作流程:定位两个指针,low放在当前数组的第一位,和high放在当前数组的最后一位,第一位为标杆。

先把标杆用另一个变量保存,从high指针开始,往前移动,如果读到当前的元素<=标杆,停止移动high指针,high++,把当前的元素覆盖到low指针所指的元素。

再开始移动low指针,如果读到当前的元素>=标杆,停止移动low指针,把当前元素覆盖到high所指的元素,low++,再开始移动high指针。

重复上述操作,直到low==high

执行一次后,本质上是将比标杆小的元素全部移动到标杆的左边,比标杆元素大的全部移动到标杆的右边,一次移动可以确定该元素的最终位置,但是左右的元素无序。故可以利用递归,从头开始,每一次返回该元素的最终位置k,下一次递归从[1,k-1],[k+1,n]进入。

空间复杂度:O(log(n))—O(n),递归,需要栈空间,最好的情况下O(log(n)),相当于完全二叉树的深度,基本有序的情况下,最坏情况下需要O(n),需要递归到底。

时间复杂度:平均下O(nlog(n)),如果是基本有序的情况下,递归传回去的指针从依次的,如1,2,3,4 k传回去的值为1,2,3。。不能让指针平衡的划分区间最坏下O(n^2)。

稳定性:不稳定。

适用性:顺序表。

选择排序

简单选择排序

操作流程:第i躺排序从a[i....n]中选择关键字最小的元素与a[i]交换,每一躺可以确定该元素的位置

空间复杂度:O(1)

时间复杂度:O(n^2)

稳定性:不稳定,如[2,2,1]第一个2会在第一躺中和1交换

堆排序

重要的算法之二

操作流程:先将待排列的数依次存储为大根堆(如果想按照从小到大排序),如果加入一个元素,需要down,如果删除需要对该堆进行down,维持大根堆的状态。如果需要输出递增序列,则将头节点放到最后,并且down一下a[1...n-1]。最后down完n个数,该数组即为有序的递增序列。该排序重代码,手算注意顺序

空间复杂度:O(1)

时间复杂度:O(nlog(n)),建堆时间在O(n),每次调整的时间复杂度为O(log(n)),有n个数需要输出,故为O(nlog(n))

稳定性:不稳定

归并排序

重要的算法之三

操作流程:个人认为该排序和快速排序有些共通之处,快排是从大的开始分,往小了走。归并排序(此处默认为二路排序)利用分支算法,开始的时候对于每两个元素有序合并成一个个子数组,将每个子数组有序合并,直到最后数组完全合并。

空间复杂度:O(n),在两两合并排序的时候需要复制数组。

时间复杂度,每趟的归并复杂度为O(n),需要O(log(n))躺归并

稳定性:稳定,再合并的时候不会改变相关关键字的次序

基数排序

操作流程:两种方式实现:MSD(最高位优先),LSD(最低位优先)此处挑LSD

该算法一共有两步,一步为分类,一步为收集

分类:对待排序的元素有d元组[k1,k2,...,kd]组成,按照组中的k1可以分成成r个类别,根据r类从小到大按照原本的顺序依次对该待排元素进行排序。如123,456,765三个元素,根据位数可以分成3元组[个,十,百],“个”可以分成10类,0,1,2,3,4,5,6,7,8,9。根据三个元素的按照个进行分类,

3 5 6

| | |

123 765 456

收集:在上述的例子中,按照循序,把每个类中的元素按照顺序拿下来,组成新的排列,123、765、456

同时该算法对于非数值的排序提供了一个思路:如按照年月日来对一群人的的生日进行排序,即对于出生年月为2012.08.09、2015.07.05、2016.9.11 可以先对日进行排列,收集为2015.07.05、2012.08.09、2016.9.11。然后对月(和上述是一样的排序) 然后是年2012.08.09、2015.07.05、2016.9.11。即对每一次排列中,在当前关键字下,最小的排列,在循环d组后,可得到所需的排列。

空间复杂度:O(r)

时间复杂度:O(d(n+r))

稳定性:稳定

posted @ 2023-05-18 10:30  dueyu  阅读(59)  评论(0)    收藏  举报