插入排序
直接插入排序;将数组分为有序和无序两部分,然后将无序数组的每个元素依次插入有序数组中,当无序数组全部插完后,则原数组排序完毕。
代码实现:
public static void insertSort(int[] arr){
if(arr == null || arr.length <= 1){
return;
}
for(int i = 1; i < arr.length; i++){
//第一个元素本身有序(只有一个)
int temp = arr[i];
int j = i - 1; // 有序部分的最后一个元素
for(; j >= 0 && arr[j] > temp ; j--){
// 元素后移
arr[j+1] = arr[j];
}
arr[j+1] = temp;
}
}
测试:
public static void printArr(int[] arr){
for(int data : arr){
System.out.print(data + "、");
}
System.out.println();
}
public static void main(String[] args) {
int[] arr = new int[]{1,3,2,6,5,8,7,9,0};
System.out.println("排序前");
printArr(arr);
System.out.println("排序后");
insertSort(arr);
printArr(arr);
}
结果:
时间复杂度
数组有序(从小到大):进行数据插入的时候,不会进入第二个循环,因此O(n);
数组无序或者逆序: 每次将一个元素插入合适位置,都需要对前面的有序数组进行一次遍历以寻找该插入的位置因此O(n*n);
空间复杂度
没有开辟额外空间因此O(1);
稳定性:
在进行插入的时候,若欲插入的元素和有序部分的某一元素值相等,最终会插入到该元素的后面因此是稳定性排序。
优化:
因为数组的前半部分已经有序,因此对于元素位置的查找可以采取二分查找。
代码实现:
public static void insertSortPlus(int[] arr){
if(arr == null || arr.length < 2){
return;
}
for(int i = 1; i < arr.length; i++){
int temp = arr[i];
int j = i - 1;
int left = 0;
int right = i - 1;
while(left <= right){
int mid = left + ((right - left) >> 1); // 防止越界,右移代替除法操作
if(arr[mid] < temp){
// 插入位置在后边
left = mid + 1;
}else{ // arr[mid] >= temp
right = mid - 1;
}
}
//可以同时处理arr[mid] >= temp
for(; j >= right+1; j--){
arr[j+1] = arr[j];
}
arr[j+1] = temp;
}
}
测试
public static void printArr(int[] arr){
for(int data : arr){
System.out.print(data + "、");
}
System.out.println();
}
public static void main(String[] args) {
int[] arr = new int[]{1,3,2,6,5,8,7,9,0};
System.out.println("排序前");
printArr(arr);
System.out.println("排序后");
insertSortPlus(arr);
printArr(arr);
}
结果:
希尔排序
希尔排序的思想就是分组执行插入排序,本质还是和插入排序是一样的,当组间距刚好是一的时候就是一次插入排序,但在最后一次插排的时候,数组经过前面的处理已经接近有序。
代码:
public static void shellSort(int[] arr){
if(arr == null || arr.length <= 1){
return;
}
// 使用step作为间距
int step = arr.length >> 1;
while(step >= 1){
for(int i = step; i < arr.length; i++){
int temp = arr[i];
int j = i - step;
for(; j >= 0 && arr[j] > temp ;j-= step){
arr[j+step] = arr[j];
}
arr[j + step] = temp;
}
step >>= 1;
}
}
public static void printArr(int[] arr){
for(int data : arr){
System.out.print(data + "、");
}
System.out.println();
}
测试:
public static void printArr(int[] arr){
for(int data : arr){
System.out.print(data + "、");
}
System.out.println();
}
public static void main(String[] args) {
int[] arr = new int[]{1,3,2,6,5,8,7,9,0};
System.out.println("排序前");
printArr(arr);
System.out.println("排序后");
shellSort(arr);
printArr(arr);
}
}
结果: