冒泡排序
核心思想:冒泡排序只会比较相邻的两个数,相邻的两个数满足大小条件时不移动,不满足大小条件时交换位置,然后指针后移一位,直到指针到达未排序的序列的倒数第二个位置,再进行下一轮排序。冒泡排序每一轮至少会使一个数到达指定的位置。
以C,D,A,F,B,E为例,下面图解为从小到大排序,且只展示了F回到自己位置,后面的数据思想相同。
第一轮结束后,F回到了自己的位置。
时间复杂度:每一次循环都有至少一个数字回到自己的位置上,那么循环数组长度那么多次就会使所有的数字回到自己的位置,因此时间复杂度为O(n^2),但冒泡排序还可以进行优化。如下图所示,实际在第三轮已经将所有的数字排序完成,第四、五、六次是不必要的操作,因为我们可以加一个标志位,当一轮中没有任何数字交换,说明已经全部排序成功,提前跳出循环,祥见代码。
所以优化后的冒泡排序的时间复杂度可以准确描述为,最好情况下,只需经过一个冒泡,时间复杂度为O(n),最坏情况下,需要n次冒泡,时间复杂度为O(n2)。平均情况下的时间复杂度也为O(n2)
空间复杂度:O(1),像这种空间复杂度为O(1)的排序算法也称为原地排序,即没有借助多余的内存空间。
Java实现:
/**
*@author 苞谷洁子
*@param arr 待排序的数组
*/
public static int[] sort(int[] arr){
if(arr == null){
return null;
}
if(arr.length == 1 || arr.length == 0){
return arr;
}
boolean flag;
for(int i = 0;i<arr.length;i++){
flag = true;
//从后往前排序的,下标为arr.length-i的已经排好序了
for(int j = 0;j<arr.length-i-1;j++){
//当前一个数字比后一个数字大,就将相邻的两个数字交换
if(arr[j]>arr[j+1]){
int temp = arr[j];
arr[j] = arr[j+1];
arr[j+1] = temp;
flag = false;
}
}
//flag标志记录当前次是否进行的修改,为true表示已经排序完成了,可以直接返回了
if(flag){
break;
}
}
return arr;
}
插入排序
核心思想:插入排序是从数组的插入演变而来的,其主要思想是将数组分为两个区域,一个是已经排序的区域,一个是未排序的区域。每一轮都是将未排序的第一个数字与排序的数字从后往前比较,边比较边将比较过的数字后移,直到找到插入的位置,将其插入。每一轮有且只有一个数字回到自己的位置,如下图所示。
时间复杂度:插入排序也分最好情况和最坏情况,在最好的情况下,数组完全为有序的,因此在无序序列第一个数字和有序序列最后数字比较时,可以直接得到要插入的位置就是当前位置,所以只需要n次操作,就能完成排序,时间复杂度为O(n);最坏情况下数组是完全逆序的,因此每一轮都要将前i个数字后移才能挪出插入的位置,时间复杂度为O(n2),平均时间复杂度为O(n2)。
空间复杂度:插入排序也是一个原地排序,没有使用多余的内存空间,空间复杂度为O(1)
Java实现:
/**
* @author 苞谷洁子
* @param arr 待排序的数据
*/
public static int[] sort(int[] arr){
if(arr == null){
return null;
}
if(arr.length == 1 || arr.length == 0){
return arr;
}
for(int i = 0;i<arr.length;i++){
int temp = arr[i];
int j = i-1;
for(;j>=0;j--){
if(temp < arr[j]){
arr[j+1] = arr[j];
}else{
break;
}
}
arr[j+1] = temp;
}
return arr;
}
选择排序
核心思想:选择排序也是将数组分为两个区域,已排序和未排序区域。它是从未排序数组中,按照要排序的大小顺序(如从大到小排序),选择出最小的数字,和未排序的第一个数字交换位置,并为已排序的数组中,依次这样,直到整个数组排序完成。如下图所示:
时间复杂度:选择排序部分最好情况和最坏情况,因为即使数组是有序的,但是每一轮仍要遍历无序的部分找出最小的数字,因此选择排序的时间复杂度为O(n^2)。
空间复杂度:选择排序也是一个原地排序算法,空间复杂度为O(1)。
Java实现:
/**
*@author 苞谷洁子
* @param arr 待排序的数组
*/
public static int[] sort(int[] arr){
if(arr == null){
return null;
}
if(arr.length == 1 || arr.length == 0){
return arr;
}
for(int i = 0;i<arr.length-1;i++){
int min = arr[i];
int n = i;
for(int j = i;j<arr.length;j++){
//选择出最小的数
if(arr[j]<min){
min = arr[j];
n = j;
}
}
if(n != i){
int temp = arr[i];
arr[i] = arr[n];
arr[n] = temp;
}
}
return arr;
}