这是我参与「第三届青训营 -后端场」笔记创作活动的第4篇笔记,今天讲一下基本的三种排序算法及其优化组合算法。
算法简介
插入排序
基本思想
将一个数插入一个已经排好序的数据中。
- 第一次循环时,从第2个数开始处理。我们将第1个数作为已经排好序的数据:当第2个数 > 第1个数时,将第2个数放在第1个数后面一个位置;否则,将第2个数放在第1个数前面。此时,前两个数形成了一个有序的数据。
- 第二次循环时,我们处理第3个数。此时,前两个数形成了一个有序的数据:首先比较第3个数和第2个数,当第3个数 > 第2个数时,将第3个数放在第2个数后面一个位置并结束此次循环;否则,再和第1个数比较。如果第3个数 > 第1个数,则将第3个数插入第1个数和第2个数中间;否则,第3个数 < 第1个数,则将第3个数放在第1个数前面。此时,前三个数形成了一个有序的数据。
- 后续的数据同理处理,直至结束。
复杂度分析
- 时间复杂度: - 在最坏的情况下,即整个数组是倒序的,比较次数 = 1 + 2 + 3 + ... + (n - 2) + (n - 1) = n * (n - 1) / 2,此时的时间复杂度为:O(n^2)。 - 在最好的情况下,即整个数组是正序的,比较次数 = n - 1,此时的时间复杂度为:O(n)。 - 平均 O(n^2)
- 空间复杂度:O(1)
快速排序
快速排序(Quick sort)是对冒泡排序的一种改进,是非常重要且应用比较广泛的一种高效率排序算法。
基本思想
快速排序是通过多次比较和交换来实现排序,在一趟排序中把将要排序的数据分成两个独立的部分,对这两部分进行排序使得其中一部分所有数据比另一部分都要小,然后继续递归排序这两部分,最终实现所有数据有序。
大致步骤如下:
- 首先设置一个分界值也就是基准值又是也称为监视哨,通过该分界值将数据分割成两部分。
- 将大于或等于分界值的数据集中到右边,小于分界值的数据集中到左边。一趟排序过后,左边部分中各个数据元素都小于分界值,而右边部分中各数据元素都大于或等于分界值,且右边部分个数据元素皆大于左边所有数据元素。
- 然后,左边和右边的数据可以看成两组不同的部分,重复上述1和2步骤,当左右两部分都有序时,整个数据就完成了排序。
复杂度分析
- 时间复杂度
- 最好情况:每次数据元素都能平均的分成两个部分。得到一个完全二叉树。如果有n个数据元素,时间复杂度为O(nlogn)
- 最坏情况:在最坏的情况下,这个数仅有右子树或左子树,比较次数为 (n-1)+(n-2) + (n-3) + … +1=n*(n-1)/2 ,因此时间复杂度为O(n^2),在待排序数据元素已经有序的情况下快速排序时间复杂度最高
- 空间复杂度O(n):快速排序是一种不稳定的排序算法,会改变数据元素的相对位置,也是内排序中平均效率最高的排序算法。
堆排序
基本思想
利用堆的性质 1、将带排序的序列构造成一个大顶堆,根据大顶堆的性质,当前堆的根节点(堆顶)就是序列中最大的元素; 2、将堆顶元素和最后一个元素交换,然后将剩下的节点重新构造成一个大顶堆; 3、重复步骤2,如此反复,从第一次构建大顶堆开始,每一次构建,我们都能获得一个序列的最大值,然后把它放到大顶堆的尾部。最后,就得到一个有序的序列了。
复杂度分析
因为堆排序无关乎初始序列是否已经排序已经排序的状态,始终有两部分过程,构建初始的大顶堆的过程时间复杂度为O(n),交换及重建大顶堆的过程中,需要交换n-1次,重建大顶堆的过程根据完全二叉树的性质,[log2(n-1),log2(n-2)...1]逐步递减,近似为nlogn。所以它最好和最坏的情况时间复杂度都是O(nlogn),空间复杂度O(1)。
优化算法
序列长度与性能
- 插入排序在短序列中速度最快
- 快速排序在中、长序列最快
- 堆排序和快速排序相差不大
pdqsort
混合排序算法
- 短序列使用插入排序
- 其他情况使用快速排序
- 快速排序不佳时使用堆排序,基于递归深度检测