常用排序算法(一)插入排序

1.基本思想

对于未排序数据,在已排序序列中从后向前扫描,找到相应位置并插入,通常以第一个元素为已排序序列。在从后向前扫描过程中,需要反复把已排序元素逐步向后挪位,为最新元素提供插入空间

2.应用场景

插入排序不适合对于数据量比较大的排序应用。但是,如果需要排序的数据量很小,例如,量级小于千,那么插入排序还是一个不错的选择。尤其当数据基本有序时,采用插入排序可以明显减少数据交换和数据移动次数,进而提升排序效率。

3.动图展示

《常用排序算法(一)插入排序》

 

4.插入操作示例

例如我们有一组数字:{5,2,4,6,1,3},我们要将这组数字从小到大进行排列。 我们从第二个数字开始,将其认为是新增加的数字,这样第二个数字只需与其左边的第一个数字比较后排好序;在第三个数字,认为前两个已经排好序的数字为手里整理好的牌,那么只需将第三个数字与前两个数字比较即可;以此类推,直到最后一个数字与前面的所有数字比较结束,插入排序完成

《常用排序算法(一)插入排序》

(1) 最好情况:序列已经是升序排列,在这种情况下,需要进行的比较操作需(n-1)次即可。

(2) 最坏情况:序列是降序排列,那么此时需要进行的比较共有n(n-1)/2次

def insertSort[T](source:ListBuffer[T])(implicit f:T=>Ordered[T]):ListBuffer[T]={
    for(i<-1 until source.length){
      for(j<-(1 to i).reverse){
        val current=source(j)
        val prev=source(j-1)
        if(current < prev){
          source(j-1)=current
          source(j)=prev
        }
      }
    }
    source
  }
def insertSort2[T](inputData: ListBuffer[T])(implicit f:T=>Ordered[T]): ListBuffer[T] = {
  for (i <- 1 until inputData.length) {
    val behindData = inputData(i)
    var j = i - 1
    while (j >= 0 && behindData < inputData(j)) {
      inputData(j + 1) = inputData(j)
      j = j - 1
    }
    inputData(j + 1) = behindData
  }
  inputData
}

5.改进思路

1》.二分插入排序

二分插入排序相对直接插入排序而言:平均性能更快,时间复杂度降至O(NlogN),排序是稳定的,但排序的比较次数与初始序列无关,相比直接插入排序,在速度上有一定提升。逻辑步骤:

① 从第一个元素开始,该元素可以认为已经被排序

② 取出下一个元素,在已经排序的元素序列中二分查找到第一个比它大的数的位置

③ 将新元素插入到该位置后

④ 重复上述两步

2》.希尔排序

希尔排序是把记录按下标的一定增量分组,对每组使用直接插入排序算法排序;随着增量逐渐减少,每组包含的关键词越来越多,当增量减至1时,整个文件恰被分成一组,算法便终止

  简单插入排序一步一步的对元素进行比较,移动,插入,比如[5,4,3,2,1,0]这种倒序序列,数组末端的0要回到首位置很是费劲,比较和移动元素均需n-1次。而希尔排序在数组中采用跳跃式分组的策略,通过某个增量将数组元素划分为若干组,然后分组进行插入排序,随后逐步缩小增量,继续按组进行插入排序操作,直至增量为1。希尔排序通过这种策略使得整个数组在初始阶段达到从宏观上看基本有序,小的基本在前,大的基本在后。然后缩小增量,到增量为1时,其实多数情况下只需微调即可,不会涉及过多的数据移动。

  我们来看下希尔排序的基本步骤,在此我们选择增量gap=length/2,缩小增量继续以gap = gap/2的方式,这种增量选择我们可以用一个序列来表示,{n/2,(n/2)/2…1},称为增量序列。希尔排序的增量序列的选择与证明是个数学难题,我们选择的这个增量序列是比较常用的,也是希尔建议的增量,称为希尔增量,但其实这个增量序列不是最优的。此处我们做示例使用希尔增量。

《常用排序算法(一)插入排序》

def xierSort[T](sou:ListBuffer[T])(implicit t:T=>Ordered[T]): ListBuffer[T] ={
    var d1:Int = sou.length
    var booleanX = true
    while(d1!=1) {
      d1 = d1/2
      for (x <- 0 until d1) {
        for (i <- Range(x + d1, sou.length, d1)) {
          var j = i - d1
          var sortTemp = sou(i)
          while (j >= 0 && sou(j) > sortTemp) {
            sou(j + d1) = sou(j) //比较如果不大于的话 ,最后又把值付给自个
            j -= d1
          }
          sou(j + d1) = sortTemp
        }
      }
    }
    sou
  }

希尔排序中对于增量序列的选择十分重要,直接影响到希尔排序的性能。我们上面选择的增量序列{n/2,(n/2)/2…1}(希尔增量),其最坏时间复杂度依然为O(n2),一些经过优化的增量序列如Hibbard经过复杂证明可使得最坏时间复杂度为O(n3/2)。

    原文作者:飞末
    原文地址: https://www.cnblogs.com/feiyumo/p/9290574.html
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞