C++编写经典算法之一:插入排序InsertionSort

“插入排序”是数列排序的算法之一。
其思路引点来自于我们平时打扑克牌的习惯。

“我们在整理扑克牌时,往往会倾向于将无序的扑克牌升序或降序的排列,其方法在于拿起一张牌,与其他牌对比,如果是升序排列,那就与左边的牌进行对比,将其放在比此牌大且比此牌小的位置,重复这个过程,就会得到一个有序的牌组。”

  1. 算法思路
    C++编写经典算法之一:插入排序InsertionSort_第1张图片
    首先,得到一个随机的数列。

C++编写经典算法之一:插入排序InsertionSort_第2张图片
左端的数字已完成排序。

C++编写经典算法之一:插入排序InsertionSort_第3张图片
然后,取出那些尚未操作的左端的数字,将其与已经操作的左侧的数字进行比较。如果左边的数字较大,交换两个数字。重复此操作,直到出现一个较小的数字或者数字到达左端。

C++编写经典算法之一:插入排序InsertionSort_第4张图片
这种情况下,由于5大于3,所以交换了数字,数字到达了左端,停止数字移动。

C++编写经典算法之一:插入排序InsertionSort_第5张图片

这样,“3”已经完成了排序。

C++编写经典算法之一:插入排序InsertionSort_第6张图片
和之前同样取出左端的数字,与左边的数字进行比较。

C++编写经典算法之一:插入排序InsertionSort_第7张图片

由于“5”大于“4”,所以交换了数字。由于“3”小于“4”,出现了更小的数字,所以“4”停止移动。

C++编写经典算法之一:插入排序InsertionSort_第8张图片

这样,“4”完成了排序。

C++编写经典算法之一:插入排序InsertionSort_第9张图片

重复上述操作,直至所有的数字完成排序。

  1. 动画演示
    C++编写经典算法之一:插入排序InsertionSort_第10张图片
  2. 代码清单及其测试结果
#include 
#include 
template 

int getSizeOfArray(T& is){
    return sizeof(is)/ sizeof(is[0]);
}

void insertionSort(int *is,int size){
    for(int i=1;i=0;j--){
            if(is[j]>is[currentIndex]){
                int cup = 0;
                cup = is[j];
                is[j] = is[currentIndex];
                is[currentIndex] = cup;
                currentIndex = j;
            }
        }
    }
}

int main() {
    using namespace std;

    clock_t startTime,endTime;

    int is[] = {2,3,5,1,0,8,6,9,7};
    int size = getSizeOfArray(is);

    cout<< "原数列:";

    for(int i = 0;i

C++编写经典算法之一:插入排序InsertionSort_第11张图片

  1. 另一种思路

我们通过动画演示和上述的代码清单可以发现,是利用不断的比较交换来实现排序的过程。但,其实,我们还有另外一种实现方法,并不会改变“插入排序”的核心思路,这个与我们平时打牌最相似,话不多说,直接看代码。

#include 
#include 
template 

int getSizeOfArray(T& is){
    return sizeof(is)/ sizeof(is[0]);
}

void moveArray(int *is,int currentIndexOfI,int currentIndexOfJ){
    for(int i = currentIndexOfI;i>currentIndexOfJ;i--){
        is[i] = is[i-1];
    }
}

void insertionSort2(int *is,int size){
    for(int i=1;i=0;j--){
            if(is[i]

C++编写经典算法之一:插入排序InsertionSort_第12张图片

通过观察,可以明显发现,这是一种将数组片段推移的实现方法,就和我们平时打牌一样,从中间发现一张较小的牌,直接找到位置,将其插入,并将右边的牌整体向右移动。

  1. 实现方法对比

在数据量小的时候,在相同的数列情况下,不同实现方式(即3小节与4小节)算法运行的时间是几乎相同的。下面看看大整数数列下,谁的性能更好。

随机数范围:r属于[0,100]

样本量(单位:个) 100 500 1000 2000 5000 10000 100000
实现方法一(单位:s) 2.2e-05 0.000521 0.002355 0.007207 0.04969 0.154 13.5
实现方法二(单位:s) 2.2e-05 0.000518 0.001811 0.008545 0.051375 0.165 15.3

我们不难发现,在样本数小于5,000时,似乎实现方法二更为省时,但样本数一旦大于5,000,很明显实现方法一更为快速。

  1. 算法分析

如果目标是把n个元素的序列升序排列,那么采用插入排序存在最好情况和最坏情况。最好情况就是,序列已经是升序排列了,在这种情况下,需要进行的比较操作需(n-1)次即可。最坏情况就是,序列是降序排列,那么此时需要进行的比较共有n(n-1)/2次。插入排序的赋值操作是比较操作的次数加上 (n-1)次。平均来说插入排序算法的时间复杂度为O(n^2)。因而,插入排序不适合对于数据量比较大的排序应用。但是,如果需要排序的数据量很小,例如,量级小于千,那么插入排序还是一个不错的选择。

你可能感兴趣的:(算法,C++,算法,插入排序,面向对象)