直接插入排序和二分插入排序

  1. /**
  2. * @Author leijs
  3. * @date 2021/8/16
  4. */
  5. public class InsertSort {
  6. public static void main(String[] args) {
  7. int[] arr = {1, 4, 3, 6, 8, 4, 9, 6, 2};
  8. int[] arr1 = insertSort(arr);
  9. for (int i = 0; i < arr1.length; i++) {
  10. System.out.print(arr1[i]);
  11. }
  12. System.out.println();
  13. int[] arr2 = insertSortWithBinarySearch(arr);
  14. for (int i = 0; i < arr2.length; i++) {
  15. System.out.print(arr2[i]);
  16. }
  17. }
  18. /**
  19. * 直接插入排序,时间复杂度O(n^2),空间复杂夫O(1)
  20. * 可以理解为打扑克牌的摸牌按照顺序放牌的位置
  21. *
  22. * @param arr
  23. * @return
  24. */
  25. public static int[] insertSort(int[] arr) {
  26. // 从第一个元素开始作为插入排序,和前面排好序的元素比较找到插入位置
  27. for (int i = 1; i < arr.length; i++) {
  28. int temp = arr[i];
  29. // 在前面排好序的数组找到插入位置
  30. for (int j = i - 1; j >= 0; j--) {
  31. if (arr[j] > temp) {
  32. // 元素向后移动
  33. arr[j + 1] = arr[j];
  34. } else {
  35. // 找到元素的插入位置结束
  36. arr[j + 1] = temp;
  37. break;
  38. }
  39. }
  40. }
  41. return arr;
  42. }
  43. /**
  44. * 二分法插入排序
  45. * 含义:在插入第i个元素的时候,对前面0~i-1元素进行折半,先跟中间元素进行比较,如果小,则对前半在进行折半
  46. * 直到left<right,然后再把第i个元素前1位与目标元素之间的所有元素后移,再把第i个元素放在目标位置上
  47. */
  48. public static int[] insertSortWithBinarySearch(int[] arr) {
  49. for (int i = 1; i < arr.length; i++) {
  50. // 要插入的元素
  51. int temp = arr[i];
  52. int left = 0;
  53. int right = i - 1;
  54. int mid = 0;
  55. while (left <= right) {
  56. // 中间位置
  57. mid = left + (right - left) / 2;
  58. // 找到新的左坐标和右坐标
  59. if (arr[mid] > temp) {
  60. // 说明要往左
  61. right = mid - 1;
  62. } else {
  63. // 说明要往右
  64. left = mid + 1;
  65. }
  66. }
  67. // 大于temp的元素向右移动,只需要关注left->当前i之间的元素
  68. for (int j = i - 1; j >= left; j--) {
  69. // 其实就是left->i之间的元素
  70. arr[j + 1] = arr[j];
  71. }
  72. // 插入元素
  73. arr[left] = temp;
  74. }
  75. return arr;
  76. }
  77. }

希尔排序

  1. /**
  2. * @Author leijs
  3. * @date 2021/8/16
  4. */
  5. public class ShellSort {
  6. public static void main(String[] args) {
  7. int[] arr = {1, 4, 3, 6, 8, 4, 9, 6, 2};
  8. int[] arr1 = shellSort(arr);
  9. for (int i = 0; i < arr1.length; i++) {
  10. System.out.print(arr1[i]);
  11. }
  12. }
  13. /**
  14. * 又叫“缩小增量排序”
  15. * 先取一个小于n的整数d1作为第一个增量,把文件的全部记录分成d1个组
  16. * 所有距离为d1倍数的记录在同一个组中。
  17. * 先在各组内进行直接插入排序,然后,取第二个增量d2
  18. *
  19. * @param arr
  20. */
  21. public static int[] shellSort(int[] arr) {
  22. int length = arr.length;
  23. // 第一个循环决定比较的间隔
  24. for (int i = length / 2; i > 0; i = i / 2) {
  25. // 第二个循环根据间隔,将整个数组分为若干个数组
  26. for (int j = i; j < length; j++) {
  27. // 第三个循环,在子数组内进行插入排序算法
  28. for (int k = j; k >= i && arr[k] < arr[k - i]; k = k - i) {
  29. int temp = arr[k];
  30. arr[k] = arr[k - i];
  31. arr[k - i] = temp;
  32. }
  33. }
  34. }
  35. return arr;
  36. }
  37. }