一、基本介绍
十种常见排序算法可以分为两大类:
比较类排序:通过比较来决定元素间的相对次序,由于其时间复杂度不能突破O(nlogn),因此也称为非线性时间比较类排序。
非比较类排序:不通过比较来决定元素间的相对次序,它可以突破基于比较排序的时间下界,以线性时间运行,因此也称为线性时间非比较类排序。
时间复杂度:对排序数据的总的操作次数。反映当n变化时,操作次数呈现什么规律。
空间复杂度:是指算法在计算机内执行时所需存储空间的度量,它也是数据规模n的函数。
稳 定 性:如果a=b,且a原本在b前面,排序之后a仍然在b的前面则称该算法是稳定的,否则称该算法不稳定。
二. 算法详解及实现
比较类排序
1. 交换排序
1> 冒泡排序
越小的元素会经由交换慢慢浮到数列的顶端。
public static void bubbleSort(int[] arr[]){
if(arr==null||arr.length<1){
return;
}
int temp;
//每次循环都会将数组中最大的一个元素确定出来排到最后
for(int i=0;i<arr.length;i++){
boolean isEnd=false;
for(int j=0;j<arr.length-1-i;j++){
if(arr[j+1]<arr[j];j++){
temp=arr[j+1];
arr[j+1]=arr[j];
arr[j]=temp;
isEnd=true;
}
}
//如果此次循环一次两两交换都没发生就退出
if(!isEnd){
break;
}
}
}
分析:
如果数组本身已经排好序,那么在i=0时进入下一个for循环中,但此次没有发生两两
交换,所以就退出了,所以时间复杂度是:O(n)
2> 快速排序
快速排序:通过一趟排序将待排记录分隔成独立的两部分,其中一部分记录的关键字均比另一部分的关键字小,则可分别对这两部分记录继续进行排序,以达到整个序列有序。
从数列中挑出一个元素,称为 “基准”(pivot);
重新排序数列,所有元素比基准值小的摆放在基准前面,所有元素比基准值大的摆在基准的后面(相同的数可以到任一边),在这个分区退出之后,该基准就处于数列的中间位置。这个称为分区(partition)操作;
递归地(recursive)对小于基准值元素的子数列和大于基准值元素的子数列排序。
public static void quickSort(int[] arr){
quickSort(arr,0,arr.length-1);
}
public static void quickSort(int arr,int left,int right){
if(left<right) return;
int i=left;
int j=right;
int pivot=arr[i];
while(i!=j){
while(a[j]>=pivot&&i<j){ 从后往前比较,如果后>=pivot,后指针往前移
j--;
}
while(a[i]<=pivot&&i<j){从前往后比较,如果前<=pivot,前指针往后移;
i++;
}
if(i<j){
//交换a[j]和a[i]在数组中的位置
int temp=arr[i];
arr[i]=arr[j];
a[j]=temp;
}
}
arr[left]=a[i];
a[i]=pivot;
quickSort(arr,left,i-1);
quickSort(arr,i+1,right);
}
分析:
2. 归并排序
1> 二路归并排序
2> 多路归并排序
参考文章:
https://blog.csdn.net/weixin_41963657/article/details/88951582