先po一张网上的图:
1.空间复杂度:
O(1): 插入排序、选择排序、冒泡排序、堆排序、希尔排序
O(logn)~O(n): 快速排序
O(n): 归并排序(通过手摇算法可以优化到O(1) ,但是时间复杂度会上升 )
O(M): 计数排序,基数排序 (M:桶的个数)
2.稳定性:
不稳定: 选择排序、堆排序、快速排序、希尔排序(快些来选一堆美女)
稳定: 插入排序、冒泡排序、归并排序、计数排序、基数排序
一、冒泡排序:
将相邻两个数两两进行比较,把大的逐渐交换到最后的位置,比较次数为n(n-1)/2。
int* bubbleSort(int* A, int n) {
int i,j,temp;
for(i=0;i<n;i++)
{
for(j=0;j<n-i-1;j++)
{
if(A[j]>A[j+1])
{
temp=A[j];
A[j]=A[j+1];
A[j+1]=temp;
}
}
}
return A;
}
二、选择排序:
从序列中选出最小值放与最左端的数交换,再从剩下的序列中选出最小值与第二个数交换,依次进行直至有序。
int* selectionSort(int* A, int n) {
// write code here
int i,j,min,temp;
for(i=0;i<n;i++)
{
min=i;
for(j=i+1;j<n;j++)
{
if(A[min]>A[j])
{
min=j;
}
}
if(min!=i)
{
temp=A[i];
A[i]=A[min];
A[min]=temp;
}
}
return A;
}
特征分析:
1、空间复杂度O(1),最好/最坏/平均时间复杂度都是O(n^2),比较次数O(n^2),移动次数O(n)。
2、选择排序是不稳定的排序方法
三、插入排序:
从序列最右端
知识点:
1.对基本有序的数列进行排序,最好的是堆排,最坏的是快速排序。
2.快速排序中,key的值选的越接近中央,即左右子序列的长度越接近,处理速度越快。
3.排序时,若不采用计数排序等科技换时间的方法,合并m个长度为n的已排序数组的时间复杂度最优为:O(mnlog(m))。
思想是:先将每个数组的第一个数提取出来,建立一个小根堆,时间复杂度O(m);然后每次输出堆顶的数,再将其所属已排序数组的后一个数放入堆顶,调节小根堆。因为我们有m*n个数,小根堆调整时间为O(logm),所以时间复杂度O(nmlogm)。
4.堆排序无论初始状态如何都是O(nlogn);
选择排序无论初始状态如何都是O(n2);
归并排序无论初始状态如何都是O(nlogn);
快速排序若初始数列有序则达到最坏程度O(n2);
冒泡排序若初始状态正序,则只需n-1次比较,一趟排序,无需移动元素,此时达到O(N);
插入排序若初始状态有序则达到最好状态O(n),若初始状态无序,则达到最坏状态O(N2);
5.归并排序算法在输入数据逆序情况下排序速度最快。
6.比较次数与序列初始状态无关的排序方法:
简单选择排序
二分插入排序
7.除了堆排序算法的比较次数是O(nlog2 n),其他的都是n(n-1)/2