【路飞】从插入排序到希尔排序

303 阅读2分钟

插入排序

原理

  • 1、从第一个位置开始,将左侧的数据看作排好序的数字,右侧的数据看作未排序的数字;
  • 2、每次将右侧的数字和左侧所有的数字做一个对比,确定它在左侧的位置;

步骤

  • 1、每次将一个待排序的记录,按其关键码值的大小插入到前面已经排序的文件中的适当位置;
  • 2、从第一个元素开始,该元素可以认为已经被排序;
  • 3、取出下一个元素,在已经排序的元素序列中从后向前扫描;
  • 4、如果该元素(已排序)大于新元素,将该元素移到下一位置;
  • 5、重复步骤3~5,直到找到已排序的元素小于或者等于新元素的位置;
  • 6、将新元素插入到该位置后;
  • 7、重复步骤2~6。

实现

function insertSort(arr) {
  for (let i = 0; i < arr.length; i++) {
    for (let j = i; j >= 0; j--) {
      if (arr[j - 1] > arr[j]) {
        [arr[j], arr[j - 1]] = [arr[j - 1], arr[j]];
      } else {
        break;
      }
    }
  }
  console.log(arr);
}
var arr = [8, 9, 1, 7, 2, 3, 5, 4, 6, 0];
insertSort(arr);

优化

将判断条件合并

function insertSort2(arr) {
  for (let i = 0; i < arr.length; i++) {
    for (let j = i; j >= 0 && arr[j - 1] > arr[j]; j--) {
      [arr[j], arr[j - 1]] = [arr[j - 1], arr[j]];
    }
  }
  console.log(arr);
}
var arr = [8, 9, 1, 7, 2, 3, 5, 4, 6, 0];
insertSort2(arr);

再次优化

减少元素交换次数

function insertSort3(arr) {
  for (let i = 0; i < arr.length; i++) {
    let temp = arr[i];
    let j = i;
    for (; j >= 0 && arr[j - 1] > temp; j--) {
      arr[j] = arr[j - 1];
    }
    arr[j] = temp;
  }
  console.log(arr);
}
var arr = [8, 9, 1, 7, 2, 3, 5, 4, 6, 0];
insertSort3(arr);

希尔排序

希尔排序是插入排序的优化

原理

    1. 将数组分成若干个子数组,每个子数组都是有序的
    1. 对每个子数组进行插入排序

实现

function shellSort(arr) {
  let len = arr.length;
  let gap = Math.floor(len / 2);
  for (gap; gap > 0; gap = Math.floor(gap / 2)) {
    for (let i = gap; i < len; i++) {
      let temp = arr[i];
      let j;
      for (j = i; j >= gap && arr[j - gap] > temp; j -= gap) {
        arr[j] = arr[j - gap];
      }
      arr[j] = temp;
    }
  }
  console.log(arr);
}
var arr = [8, 9, 1, 7, 2, 3, 5, 4, 6, 0];
shellSort(arr);

分析

  • 1、第一轮循环,为了动态设置gap大小;第二轮循环和第三轮循环是插入排序的实现;
  • 2、第一次gap设为了4,然后以4为间隔将[8,2]、[9,3]、[1,5]、[7,4]、[2,6]、[3,0]两两做比较,将小的值放前面,比如将[8,2]调整为[2,8];
  • 3、第二次将gap设为了1,这时就是做了正常的插入排序。

总结

希尔排序是插入排序的升级版本,但是希尔排序是不稳定的排序。比如将gap设置为4的时候,如果数组拆分为了[2,8]、[3,9]、[1,5]、[4,7],两两做比较时,数组的第一个值总是比第二个小。这时候这轮循环就是多余的操作。

写在最后

  • 文中如有错误,欢迎在评论区指正,如果这篇文章帮到了你,欢迎点赞关注