

一直想总结一下最常用的排序算法,自己写一下代码并运行一下记忆更深刻
说明
每步将一个待排序的记录,按其排序码大小,插到前面已经排序的文件中的适当位置,直到全部插入完为止。
原理:从待排序的n个记录中的第二个记录开始,依次与前面的记录比较并寻找插入的位置,每次外循环结束后,将当前的数插入到合适的位置。

平均时间复杂度
平均复杂度 O(n²)
最好情况 O(n)
最坏情况 O(n²)
空间复杂度O(1);
稳定性 稳定
适用场景
插入排序由于O( n2 )的复杂度,在数组较大的时候不适用。它适用于简单数据排序。
代码
/**
* 简单插入排序
*/
public class InsertSort {
public static void insertSort(int[] arr){
int temp;
int length = arr.length;
for(int i=1;i<length;i++){
int j = i-1;
temp = arr[i];
while(j>=0 && arr[j] > temp){
arr[j+1] = arr[j];
j--;
}
if(j != i-1){
arr[j+1] = temp;
}
}
}
}
平均时间复杂度
平均复杂度 O(nlogn)
最好情况 O(n log²n)
最坏情况 O(n log²n)
空间复杂度O(1);
稳定性 不稳定
适用场景
Shell排序虽然快,但是毕竟是插入排序,其数量级并没有后起之秀–快速排序O(n㏒n)快。在大量数据面前,Shell排序不是一个好的算法。但是,中小型规模的数据完全可以使用它。
代码
/**
* 快速排序
*/
public class QuickSort {
public static void quickSort(int[] arr,int start,int end){
if(start>end) return;
int left = start;
int right = end;
int base = arr[start];
while(left != right){
while(left<right && arr[right]>=base){right--;}
while(left<right && arr[left] <= base){left++;}
if(left<right){
swap(arr,left,right);
}
}
swap(arr,start,left);
quickSort(arr,start,left-1);
quickSort(arr,left+1,end);
}
public static void swap(int[] arr,int left,int right){
int temp = arr[left];
arr[left] = arr[right];
arr[right] = temp;
}
}
平均时间复杂度:O(n2)
平均复杂度 O(n²)
最好情况 O(n)
最坏情况 O(n²)
空间复杂度O(1);
稳定性 稳定
适用场景
它适用于简单数据排序。
代码
/**
* 冒泡排序
*/
public class BubleSort {
public static void bubbleSort(int[] array){
int length = array.length;
for(int i=0;i<=length-1;i++){
boolean swap = Boolean.FALSE;
for(int j=0;j<length-1-i;j++){
if(array[j]>array[j+1]){
swap(array,j,j+1);
swap = Boolean.TRUE;
}
}
if(!swap){
//已经没有交换了,跳出循环
break;
}
}
}
/**
* 交换函数
* @param array
* @param left
* @param right
*/
public static void swap(int[] array,int left,int right){
// 算法一
int temp = array[left];
array[left] = array[right];
array[right] = temp;
// 算法二
// array[left] = array[left] +array[right];
// array[right] = array[left] - array[right];
// array[left] = array[left] - array[right];
}
}
平均时间复杂度
平均复杂度 O(nlogn)
最好情况 O(nlogn)
最坏情况 O(n²)
空间复杂度O(logn);
稳定性 不稳定
适用场景
快速排序在大多数情况下都是适用的,尤其在数据量大的时候性能优越性更加明显。但是在必要的时候,需要考虑下优化以提高其在最坏情况下的性能。
代码
/**
* 快速排序
*/
public class QuickSort {
public static void quickSort(int[] arr,int start,int end){
if(start>end) return;
int left = start;
int right = end;
int base = arr[start];
while(left != right){
while(left<right && arr[right]>=base){right--;}
while(left<right && arr[left] <= base){left++;}
if(left<right){
swap(arr,left,right);
}
}
swap(arr,start,left);
quickSort(arr,start,left-1);
quickSort(arr,left+1,end);
}
public static void swap(int[] arr,int left,int right){
int temp = arr[left];
arr[left] = arr[right];
arr[right] = temp;
}
}
说明
选择类排序的基本方法是:每步从待排序记录中选出排序码最小的记录,顺序放在已排序的记录序列的后面,直到全部排完。

时间复杂度
平均复杂度 O(n²)
最好情况 O(n²)
最坏情况 O(n²)
空间复杂度O(1);
稳定性 不稳定
适用场景
选择排序实现也比较简单,由于固有的O(n2)复杂度,选择排序在海量数据面前显得力不从心。因此,它适用于简单数据排序。
代码
/**
* 简单选择排序
*/
public class SelectionSort {
public static void selectionSort(int[] arr){
int length = arr.length;
int minIndex;
for(int i=0;i<length -1;i++){
minIndex = i;
for(int j= i+1;j<=length-1;j++){
if(arr[j] < arr[minIndex]){
minIndex = j;
}
}
int temp = arr[i];
arr[i] = arr[minIndex];
arr[minIndex] = temp;
}
}
}
说明
平均时间复杂度
平均复杂度 O(nlongn)
最好情况 O(nlogn)
最坏情况 O(nlogn)
空间复杂度O(1);
稳定性 不稳定
适用场景
堆排序在建立堆和调整堆的过程中会产生比较大的开销,在元素少的时候并不适用。但是,在元素比较多的情况下,还是不错的一个选择。尤其是在解决诸如“前n大的数”一类问题时,几乎是首选算法。
代码
参考:
[算法总结] 十大排序算法
十种排序算法