import java.util.Arrays; public class Algorithm { public static void main(String[] args) { Integer[] arr = {2, 5, 6, 8, 1, 3}; InsertionSort.sort(arr); System.out.println(Arrays.toString(arr)); } } class InsertionSort { private InsertionSort() {} public static <E extends Comparable> void sort(E[] arr) { for (int i = 1; i < arr.length; i++) { /** * 循环不变量:arr[i...n)未排序,而arr[0...i)已排序 * arr[i]从后向前依次和arr[0...i)中的元素进行对比,谁比它大就和谁互换位置,直到前面的元素都比它小 * 和选择排序不同的是,选择排序每次排好的arr[0...i)不会再变动,而插入排序会一直变动 */ for (int j = i; j > 0; j--) { if (arr[j].compareTo(arr[j - 1]) < 0) { E tem; tem = arr[j]; arr[j] = arr[j - 1]; arr[j - 1] = tem; } /** * 如果arr[i - 1]已经比arr[i]小了,说明左边所有数都比arr[i]小,就不用再往前比较了 */ else { break; } } // /** // * if()语句判断的条件可以一同写进for()循环,省去了break语句的跳转,简化代码 // */ // for (int j = i; j > 0 && arr[j].compareTo(arr[j - 1]) < 0; j--) { // // E tem; // tem = arr[j]; // arr[j] = arr[j - 1]; // arr[j - 1] = tem; // } } } }
import java.util.Arrays; public class Algorithm { public static void main(String[] args) { Integer[] arr = {2, 5, 6, 8, 1, 3}; InsertionSortBetter.sort(arr); System.out.println(Arrays.toString(arr)); } } class InsertionSortBetter { private InsertionSortBetter() {} public static <E extends Comparable> void sort(E[] arr) { for (int i = 1; i < arr.length; i++) { /** * 循环不变量:arr[i...n)未排序,而arr[0...i)已排序 * 将arr[i]先暂存起来,从后向前依次和arr[0...i)中的元素进行对比,谁比它大谁就往后挪一位,直到前面的元素都比 * 它小,然后将arr[i]放在j这个位置 */ E tem = arr[i]; int j; for (j = i; j > 0 && tem.compareTo(arr[j - 1]) < 0; j--) { arr[j] = arr[j - 1]; } arr[j] = tem; } } }
插入排序法的复杂度也是O(n^2)
但是和选择排序相比,当一个数组本身的有序程序很高的时候,插入排序可能只要将arr[i]和arr[i + 1]对比一次就可以结束内循环,此时插入排序法的复杂度会降到O(n);而选择排序却一定要遍历所有arr[i...n]所有的元素才能确保找到最小值
所以当数组的有序程度较高时,推荐使用插入排序
import java.util.Arrays; import java.util.Random; public class Algorithm { public static void main(String[] args) { Integer[] testScale = {10000, 100000}; for (Integer n : testScale) { /** * 测试随机数组排序性能 */ Integer[] randomArr = ArrayGenerator.generatorRandomArray(n, n); /** * 测试有序数组排序性能 */ Integer[] sortedArr = ArrayGenerator.generatorSortedArray(n, n); /** * Arrays.copyOf()方法复制数值的数值,为了测试更具有对比性 */ Integer[] arr1 = Arrays.copyOf(randomArr, randomArr.length); Integer[] arr2 = Arrays.copyOf(randomArr, randomArr.length); Integer[] arr3 = Arrays.copyOf(sortedArr, sortedArr.length); Integer[] arr4 = Arrays.copyOf(sortedArr, sortedArr.length); System.out.println("测试随机数组排序性能"); System.out.println(); Verify.testTime("SelectionSort", randomArr); Verify.testTime("InsertionSort", arr1); Verify.testTime("InsertionSortBetter", arr2); System.out.println(); System.out.println("测试有序数组排序性能"); System.out.println(); Verify.testTime("SelectionSort", sortedArr); Verify.testTime("InsertionSort", arr3); Verify.testTime("InsertionSortBetter", arr4); System.out.println(); } } } class InsertionSort { private InsertionSort() {} public static <E extends Comparable> void sort(E[] arr) { for (int i = 1; i < arr.length; i++) { for (int j = i; j > 0; j--) { if (arr[j].compareTo(arr[j - 1]) < 0) { E tem; tem = arr[j]; arr[j] = arr[j - 1]; arr[j - 1] = tem; } else { break; } } } } } class InsertionSortBetter { private InsertionSortBetter() {} public static <E extends Comparable> void sort(E[] arr) { for (int i = 1; i < arr.length; i++) { E tem = arr[i]; int j; for (j = i; j > 0 && tem.compareTo(arr[j - 1]) < 0; j--) { arr[j] = arr[j - 1]; } arr[j] = tem; } } } class SelectionSort { private SelectionSort(){} public static<E extends Comparable<E>> void sort(E[] arr){ for (int i = 0; i < arr.length - 1; i++) { int minIndex = i; for (int j = i + 1; j < arr.length; j++) { if (arr[j].compareTo(arr[minIndex]) < 0) { minIndex = j; } } if (i != minIndex) { E tem; tem = arr[minIndex]; arr[minIndex] = arr[i]; arr[i] = tem; } } } } class ArrayGenerator { private ArrayGenerator (){} public static Integer[] generatorRandomArray (Integer n, Integer maxBound){ Integer[] arr = new Integer[n]; Random random = new Random(); for (int i = 0; i < n; i++) { arr[i] = random.nextInt(maxBound); } return arr; } public static Integer[] generatorSortedArray (Integer n, Integer maxBound){ Integer[] arr = new Integer[n]; for (int i = 0; i < n; i++) { arr[i] = i; } return arr; } } class Verify { private Verify (){} public static<E extends Comparable<E>> boolean isSorted(E[] arr){ for (int i = 0; i < arr.length - 1; i++) { if (arr[i].compareTo(arr[i + 1]) > 0) { return false; } } return true; } public static<E extends Comparable<E>> void testTime(String AlgorithmName, E[] arr) { long startTime = System.nanoTime(); if (AlgorithmName.equals("SelectionSort")){ SelectionSort.sort(arr); } if (AlgorithmName.equals("InsertionSort")) { InsertionSort.sort(arr); } if (AlgorithmName.equals("InsertionSortBetter")) { InsertionSortBetter.sort(arr); } long endTime = System.nanoTime(); if (!Verify.isSorted(arr)){ throw new RuntimeException(AlgorithmName + "算法排序失败!"); } System.out.println(String.format("%s算法,测试用例为%d,执行时间:%f秒", AlgorithmName, arr.length, (endTime - startTime) / 1000000000.0)); } }