zoukankan      html  css  js  c++  java
  • 【经典算法】基本的排序算法:插入排序

    引言

    An insertion sort starts by considering the two first elements of the array data,which are data[0] and data[1]. if they are out of order, and interchange takes place. Then,the third element, data[2], is considered and inserted into its proper place.If data[2] is less than data[0] and data[1],these two elements are shifted by on position; data[0] is place at position  i, data[1] at position 2,and data[2] at position 0. If data[2] is less than data[1] and not less than data[0],then only data[1] is moved to position 2 and its place is taken by data[2]. If finally, data[2] is not less than both its predecessors,it stays in its current position,Each element data[i] is inserted into its proper location j such the 0<=j<=i, and all elements greater than data[i] are moved by one position.

    译: 插入排序首先考虑data中的前两个元素,即data[0]和data[1]。如果它们的次序颠倒了,就交换它们。然后,考虑第三个元素data[2],将其插入到合适的位置上。如果data[2]同时小于data[0]和data[1],那么data[0]和data[1]都要移动一个位置;data[0]放在位置1上,data[1]放在位置2上,而将data[2]放在位置0上。如果data[2]小于data[1],而不于data[0],那么只须把data[1]移动到位置2上,并由data[2]占据它的位置。最后,如果data[2]不小于前两个元素,它将保留在当前的位置。每一个元素data[i]都要插入到合适的位置j上,使0<=j<=i,所有比data[i]大的元素都要移动一个位置。

    插入排序算法伪码与实现

    插入排序算法的要点如下:

    insertionsort(data[],n){
      for(i=1; i<n; i++)
         move all elements data[j] greater than data[i] by one position;
         place data[i] in its proper position;
    }

    注意,在每次迭代中,排序只限于数组的一小部分,并且只在最后一次迭代中才涉及到整个数组。如下图所示是当对数组[5 2 3 8 1]行insertionsort()方法时,数组所发生的一系变动。

    因数组中只有一个元素已排序,所以算法从第二元素位置即位置1开始排序。接着,对于每一个元素tmp = data[i],所有比tmp大的位素都要复制到下一位置上,而把tmp放在合适的位置上。

    实现代码如下:

    template< class T>
    void insertionsort(T data[], int n){
            for(int i =1, j; i<n; i++){
                T tmp = data[i];
                for(j =i; i>0&&tmp< data[j-1]; j--)
                     data[j] = data[j-1];
                data[j] =tmp;
            }
    }

    插入排序的一个优点是只有需要时才对数组排序。如果数组已经排好序了,就不再对数组进行移动;只有变量tmp得到初始化,存储在变量中的值返回值原位置。可以识别出已排序的数组部分,并相应停止,但忽视元素可以已在合适位置上的事实。一个缺点是:如果插入数据项,所有比插入元素大的元素都必须移动。插入操作不是局部的,可能需要移动大量的元素。

    算法分析

    为了获取insertionsort()算法执行的移动和比较次数,首先要注意,外层的for语句执行n-1次。但是,比data[i]大的元素移动一个位置的次数并不总是相同的。

    最好的情况是:数据已排好序。对于每个位置i,只需比较一匀,这样就只需进行n-1次比较(其数量级是o(n))和2(n-1)次移动,所有的移动和比较都是多余的。最坏的情况是:数据按相反顺序排序。在这种情况下,对于外层for的每次迭代i,都比较i次,即所有迭代的比较总数是


    内层for中的赋值次数可以用相同的公式计算。把tmp在外层for中加载和卸载的次数加起来,得到总的移动次数:

    前面我们只考虑了极端情况。如果数据是随机排序的,结果如何呢?假设数据项占用数组单元的概率相等,在外层for的迭代i中,data[i]与其它元素的平均比较次数计算如下:

    为了求得所有比较次数的平均值,对于所有的迭代i来说,都必须从1开始一直累加到n-1为止。结果是


    它的时间复杂度是O(n^2),大约是最坏情况下的比较次数的1/2。按照相同的方式,可以确定在外层for的迭代i中,data[i]需要移动0,1,..i-1次:即

    次,加上一定分会发生的两次移动。因此,在外层for中所有迭代中,平均移动次数为

    其中时间复杂度为O(n^2)。

    综上所述,对于随机顺序的数组来说,移动和比较的次数是与最好情况接近,还是与最坏情况接近?遗憾的是,它接近于后者,即:当数组的元素加倍时,平均需要付出4倍的努力来排序。

    参考文献

    [1] Adam Drozdek , Data Structures and Algorithms in C++,Third Edition.

    =========================================================

    转载请注明出处:http://blog.csdn.net/ songzitea/article/details/8864084
    =========================================================
  • 相关阅读:
    数学之路-python计算实战(5)-初识numpy以及pypy下执行numpy
    从Set里面取出有序的记录
    freemarker 模板中定义变量
    MySql的事务操作与演示样例
    两个栈实现一个队列的加入、删除功能
    UVA 1156
    《品牌洗脑》:利用人类潜意识帮助营销的一些方法和实例。4星。
    《大转换》,计算会像电力一样变成基础设施,基本是作者10年前写的《IT不再重要》的修订版,3星。
    《造梦者:迪斯尼如何点亮神奇的创意》:各个迪斯尼乐园的建造过程,不含上海和香港的,没意思。2星。
    《新媒体营销圣经:引诱,引诱,引诱,出击!》:美国主要新媒体上的营销策略与实例点评,离中国有点远。2星
  • 原文地址:https://www.cnblogs.com/riskyer/p/3281358.html
Copyright © 2011-2022 走看看