1.折半插入排序:
- 折半插入排序实际上是对直接插入排序的优化,通过折半查找来找到要插入的位置,再搬移元素,最后插入即可。
- 思路分析:
- 定义low为有序部分的第一个位置,high为有序部分的最后一个位置,通过折半查找的方法,不断更新low和high的位置,直到 low>high,此时high+1即为我们要插入的位置。
- 直接插入排序是在每一次比较时,就进行数据的搬移;而折半插入排序是在找到插入位置后,通过循环一次性将high+1位置的元素到有序部分的最后一个元素j进行搬移,最后插入本次的value值到high+1位置。
- 代码实现如下:
package www.first;
import java.util.Scanner;
public class HalfInsertSort {
public static void halfInsertSort(int[] arr){
if(arr.length<=1||arr==null){
return;
}else{
//i为无序部分的第一个元素位置
for(int i = 1;i<arr.length;i++){
//存储无序元素的值,方便比较
int value = arr[i];
//有序部分的第一个元素位置
int low = 0;
//有序部分的最后一个元素位置
int high = i-1;
while(low<=high){
int mid =(low+high)/2;
if(value<arr[mid]){
high = mid-1;
}else{
low = mid+1;
}
}
//此时已经找到插入位置,为high+1,开始搬移元素
//将high+1~j位置的元素都往后搬移一位
int j = i-1;
for(;j>high;j--){
arr[j+1] = arr[j];
}
//循环之后,此时的j为high
//将high+1位置赋值为我们的value
arr[j+1] = value;
}
}
}
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
String str = scanner.nextLine();
String[] s = str.split(" ");
int[] array = new int[s.length];
for(int i = 0;i<s.length;i++){
array[i] = Integer.parseInt(s[i]);
}
halfInsertSort(array);
for(int i:array){
System.out.print(i+" ");
}
}
}
结果如下:
- 折半插入排序的时间复杂度,空间复杂度都与直接插入排序相同;也是一个稳定的排序算法。
- 折半插入排序与直接插入排序的比较:
我随机生成了10万条有序数据和10万条无序数据,我们来看看结果:
可以看出,折半插入排序在无序的情况下要优于直接插入排序;但是在近乎有序的情况下,直接插入排序要比折半插入排序好一点,因为直接插入只用比较一次。
2.希尔排序:
- 思路分析:希尔排序通过将数据分成不同的组,先对每一组进行排序,此时的数据已经大部分有序,然后再对所有元素进行一次插入排序,以减少数据交换和移动的次数
- 代码实现:
public class ShellSort {
public static void shellSort(int[] arr){
if(arr.length<=1||arr==null){
return;
}else{
int step = arr.length/2;
while(step>=1){
for(int i = step;i<arr.length;i++){
int value = arr[i];
int j = i-step;
for(;j>=0;j-=step){
if(value<arr[j]){
arr[j+step] = arr[j];
}else{
break;
}
}
arr[j+step] = value;
}
step/=2;
}
}
}
public static void main(String[] args) {
int[] arr = new int[]{1,2,5,6,8,2,3,5,2};
shellSort(arr);
for(int i:arr){
System.out.print(i+" ");
}
}
}
结果如下:
- 希尔排序是按照不同步长对元素进行插入排序,当刚开始元素无序的时候,步长最大,插入排序的元素个数很少;当步长为1时,元素基本有序了,再进行插入排序就会大大提高效率。
- 希尔排序的时间复杂度为O(nlogn),空间复杂度为O(1),但不是一种稳定的排序算法,因为相同的元素可能在各自的插入排序中移动。
- 希尔排序与直接插入排序、折半插入排序的对比:
随机生成10万条数据分别进行三种方式的排序,结果如下:
可见,希尔排序的效率远远高于直接插入排序。