美文网首页
插入排序(insertion sort)

插入排序(insertion sort)

作者: 水中的蓝天 | 来源:发表于2022-08-18 00:02 被阅读0次
10大排序算法.png
  • 插入排序是稳定排序
  • 插入排序的时间复杂度与逆序对的数量成正比关系,逆序对的数量越多 插入排序的时间复杂度就越高
  • 最坏、平均时间复杂度:O(n^2) 最好时间复杂度:O(n) 空间复杂度:O(1)
  • 当逆序对的数量极少时,插入排序的效率特别高,甚至速度比O(nlogn)级别的快速排序还要快

插入排序的执行流程:

  1. 在执行过程中,插入排序会将序列分为2部分
  • 头部是已经排好序的,尾部是待排序的
    2.从头开始扫描每一个元素
    -每当扫描到一个元素,就将它插入到头部合适的位置,使得头部数据依然保持有序
插入排序简单实现

for(int begin = 1;begin < list.length;begin++){
   //保留begin
  int curr = begin;
  //cmp: 对比两个元素大小,swap:交换两个元素
  while(curr > 0 && cmp(curr,curr-1) < 0) {
      swap(curr,curr-1);
      curr--;
  }

}

插入排序优化:将交换转为挪动
1.先将待插入的元素备份
2.头部有序数据中比待插入元素大的 都朝尾部方向挪动1个位置
3.将待插入元素放到最终的合适位置


for(int begin = 1;begin < list.length;begin++) {

  int curr = begin;
  //1.先将待插入的元素备份
  int val = list[curr];
  //cmp: 对比两个元素大小
  while(curr > 0 && cmp(val,list[curr-1]) < 0) {
        //2.将头部有序数组比当前大的 都向尾部方向移动一位 
        list[curr] = list[curr-1];
       curr--;
  }

  //3.将待插入元素放到最终的合适位置
  list[curr] = val;

}

插入排序再次优化:在元素val的插入过程中,可以先二分搜索出合适的插入位置,然后再将元素val插入 ;如此就减少了比较次数,但是时间复杂度还是O(n^2)


for(int begin = 1;begin < list.length;begin++) {
    //传入当前元素位置和当前元素合适插入的位置
    insert(begin, findInsetIdx(list, begin));
}

//将source位置元素插入到dest位置
private void insert(int[] list, int source, int dest) {
     //1.先将待插入的元素备份
     int val = list[source];
    //2.将[dest, source)范围内的元素往右挪动一个单位,靠后的先挪动
    for(int i = source ; i > dest ;i-- ) {
          list[i] = list[i-1];
   }
   //3.将val放入合适的位置
   list[dest] = val;
}

//二分查找 要求找到第一个大于val的位置
int findInsetIdx:(int[] list, int index) {
   if(list==null || list.length==0) return -1;
  int val = list[index];
  //左闭右开区间,已经排好序的区间是[0,index)
  int begin = 0;
  int end = index;
  while(begin < end) {
     int mid = (begin + end)>>1;
     if(val < list[mid]) {
         end = mid;
      }else  {//val >= list[mid]
         begin = mid + 1;
      }  
   }
   return begin;
}

相关文章

网友评论

      本文标题:插入排序(insertion sort)

      本文链接:https://www.haomeiwen.com/subject/ywdfirtx.html