今天理理排序算法
算法 | 最好 | 最坏 | 平均 | 空间复杂度 | 什么情况下发挥最好 | 什么情况下发挥最坏 | 稳定 | 属于什么排序 |
---|---|---|---|---|---|---|---|---|
直接插入排序 | O(n) | O(n2) | O(n^2) | 1 | 初始正序 | 初始反序 | √ | 插入排序 |
二分插入排序 | O(n^2) | O(n) | O(n^2) | 1 | n比较大 | n小,初始排好序 | √ | 插入排序 |
希尔排序 | O(nlogn) | 1 | × | 插入排序 | ||||
简单选择排序 | O(n^2) | 1 | × | 选择排序 | ||||
堆排序 | O(nlogn) | 1 | × | 选择排序 | ||||
冒泡排序 | O(n) | O(n^2) | O(n^2) | 1 | 初始正序 | 初始反序 | √ | 交换排序 |
快速排序 | O(nlogn) | O(logn) | n较大时 | 序列基本有序时 | × | 交换排序 | ||
归并排序 | O(nlogn) | O(n) | 一般用于对总体无序,但是各子项相对有序的数列 | √ | ||||
基数排序 | O(d(n+r)),d为位数,r为基数 | √ |
表格目前先这样,还有可以完善的地方。
总结:
一、稳定性:
稳定:冒泡排序、插入排序、归并排序和基数排序
不稳定:选择排序、快速排序、希尔排序、堆排序
二、平均时间复杂度
O(n^2):直接插入排序,简单选择排序,冒泡排序。
在数据规模较小时(9W内),直接插入排序,简单选择排序差不多。当数据较大时,冒泡排序算法的时间代价最高。性能为O(n^2)的算法基本上是相邻元素进行比较,基本上都是稳定的。
O(nlogn):快速排序,归并排序,希尔排序,堆排序。
其中,快排是最好的, 其次是归并和希尔,堆排序在数据量很大时效果明显。
三、排序算法的选择
1.数据规模较小
(1)待排序列基本序的情况下,可以选择直接插入排序;
(2)对稳定性不作要求宜用简单选择排序,对稳定性有要求宜用插入或冒泡
2.数据规模不是很大
(1)完全可以用内存空间,序列杂乱无序,对稳定性没有要求,快速排序,此时要付出log(N)的额外空间。
(2)序列本身可能有序,对稳定性有要求,空间允许下,宜用归并排序
3.数据规模很大
(1)对稳定性有求,则可考虑归并排序。
(2)对稳定性没要求,宜用堆排序
4.序列初始基本有序(正序),宜用直接插入,冒泡
快速排序(最爱考,最爱用)
public void quickSort(int[] a, int low, int high) {
if(low<high){ //如果不加这个判断递归会无法退出导致堆栈溢出异常
int middle = getMiddle(a,low,high);
quickSort(a, low, middle-1);
quickSort(a, middle+1, high);
}
}
//比基准元素小的放到基准元素的左边,大的放到右边
private int getMiddle(int[] a, int low, int high) {
int pivot = a[low];//基准元素
while(low<high){
while(low<high && a[high]>=pivot ){
high--;
}
if(low<high)
a[low++] = a[high];
while(low<high && a[low]<=pivot ){
low++;
}
if(low<high)
a[high--] = a[low];
}
a[low] = pivot ;
return low;
}
冒泡排序:
public void bubbleSort(int[] a){
for (int i = 0; i < a.length; i++) {
for(int j = 0; j<a.length-i-1; j++){
//这里-i主要是每遍历一次都把最大的i个数沉到最底下去了,没有必要再
//替换了
if(a[j]>a[j+1]){
int temp = a[j];
a[j] = a[j+1];
a[j+1] = temp;
}
}
}
}
还有好几个,以后再写吧。。。。待续