常用的排序算法有:
选择排序
插入排序
冒泡排序
归并排序
快速排序
希尔排序
堆排序
计数排序
桶排序
基数排序
不稳定排序算法有:选择排序,快速排序,希尔排序,堆排序。
排序算法实现见base-sortcode
每次从未排序数组元素中选择最值,最值与未排序数组的首个元素交互位置。因其会导致数组元素位置错乱(相同元素不能保证顺序),故是不稳定排序。
算法复杂度:O(n*n)
将待排序元素插入到已排序的数组中,一般从已排序元素的末尾开始比较,直到将其移动到前后值大小合适的位置。
O(n*n)
比较相邻元素的大小,并交换位置。数组将逐渐趋于有序。当在一次比较过程中没有发生交换,则排序结束。
算法复杂度:O(n*n)
分而治之。将待排序部分分为若干个待排序的小部分,对每一部分采用一种排序算法,最后合并已排序的部分。
快速排序、希尔排序、桶排序都使用了分而治之的思想。
算法复杂度:O(n*logn)
选择一个轴(pivot)元素,将待排序数组分为左右两部分,使得左边元素都不大于pivot,右边元素都不小于pivot,这样一轮排序结束; 继续重复以上步骤,分别对左侧和右侧数据排序。
O(n*logn)
基本有序的数组用快排,算法复杂度退化为O(n*n)
。分而治之,每一次排序将待排序部分按照步长划分为n个待排序部分,待排序部分可以按照插入排序或其他排序算法。 步长最好为 7,5,3,1这种。最后的步长是1就完成了排序。
堆排序中的堆可分为大顶堆、小顶堆。 大顶堆的特性是: a[i]>=a[2*i+1] 并且 a[i]>=a[2*i+2],即 我们虚构了一颗二叉树,所有非叶子节点的值不小于其左右子树中元素值;反之为小顶堆。 每次把堆顶元素移走(移到已排序队列),需要调整堆,调整后满足这个特性。
以空间换时间,申请 max-min个int内存,每个int存储数组元素重复次数,内存块下标就是数组元素。
算法复杂度:O(n)
,但是数组元素个数被放大了,可能是n的好多倍!
改进计数排序,不申请大量内存,将数组元素哈希分配到x个桶,对桶内的元素进行其他排序算法。
把数组元素依次对个位放到10*n
的二维数组中,如28放到下标为8的数组里 a[8][...];然后依次处理十位、百位...,直到所有的元素都放到a[0][...]里。
算法复杂度:O(kn)
选择排序、插入排序、堆排序都是维护了一个排序空间(到排序结束也不会改变),逐渐扩大这个排序空间。所以对选取最大k个数可以考虑这种算法。 选取最大k个数,可以维护一个k个元素的空间,尝试将数组元素放入到k个元素中。