插入排序算法

算法描述
一般來說,插入排序都采用in-place在數(shù)組上實(shí)現(xiàn)。具體算法描述如下:

  • 從第一個元素開始,該元素可以認(rèn)為已經(jīng)被排序
  • 取出下一個元素,在已經(jīng)排序的元素序列中從后向前掃描
  • 如果該元素(已排序)大于新元素,將該元素移到下一位置
  • 重復(fù)步驟3,直到找到已排序的元素小于或者等于新元素的位置
  • 將新元素插入到該位置后
  • 重復(fù)步驟2~5

插入排序的c++代碼:

template<typename T>
void insertionSort(T arr[], int n)
{
    for (int i = 1; i < n; i++)
    {
        for (int j = i; j > 0; j--)
        {
            if (arr[j] < arr[j - 1])
            {
                swap(arr[j], arr[j - 1]);
            }
            else
                break;
        }
    }
}

接下來比較selectionSort和insertionSort的性能。由于對同一數(shù)組進(jìn)行排序才有可比性,因此需要對隨機(jī)生成的數(shù)組復(fù)制一份,然后提供給兩個排序算法。在SortTestHelper()中添加一個拷貝數(shù)組的函數(shù)copyArray()

//此處也可考慮用函數(shù)模板,只不過涉及到深拷貝的知識,簡單起見用了int型
    int *copyArray(int a[], int n)
    {
        int *arr = new int[n];
        //copy()函數(shù)包含在std中,a原數(shù)組的頭指針,a+n原數(shù)組的尾指針,arr目的數(shù)組的頭指針
        copy(a, a + n, arr);
        return arr;
    }

測試代碼如下:

#include "SortTestHelper.h"
#include "selectionSort.h"
#include "insertionSort.h"
#include <iostream>
using namespace std;

int main()
{
    int n = 10000;
    int *arr = SortTestHelper::generateRandomArray(n, 0, n);
    int *arr2 = SortTestHelper::copyArray(arr, n);
    SortTestHelper::testSort("selectionSort:", selectionSort, arr, n);
    SortTestHelper::testSort("insertionSort:", insertionSort, arr2, n);
    
    delete[] arr;
    delete[] arr2;
    system("pause");
    return 0;
}

結(jié)果:

selectionSort:0.153s
insertionSort:2.8s

理論上分析,插入排序應(yīng)該比選擇排序要快,而上述測試用例表明選擇排序更快。為什么會有這種結(jié)果呢?
事實(shí)上,對于插入排序,在遍歷的同時也在不斷的進(jìn)行交換操作,而交換操作比賦值操作更耗時,因?yàn)槊恳淮谓粨Q操作的背后都有三次賦值操作。
接下來對插入排序算法做些改進(jìn)。代碼如下:

template<typename T>
void insertionSort(T arr[], int n)
{
    for (int i = 1; i < n; i++)
    {
        //尋找arr[i]合適的插入位置
        //將arr[i]賦值一份e,用e和其前面的元素進(jìn)行比較,找到應(yīng)該插入的位置j后再將e賦值給arr[j]
        T e = arr[i];
        int j;//保存元素e應(yīng)該插入的位置
        for (j = i; j > 0; j--)
        {
            if (e < arr[j - 1])
            {
                arr[j]=arr[j-1];
            }
            else
                break;
        }
        arr[j] = e;
    }
}

測試后結(jié)果如下:

selectionSort:0.155s
insertionSort:0.084s

為了進(jìn)一步說明改進(jìn)算法的性能,在SortTestHelper()中定義一個生成近乎有序的隨機(jī)數(shù)的函數(shù),GenerateNearlyOrderedArray()

//近乎有序數(shù)組可看成是從有序數(shù)組中隨機(jī)挑選幾組數(shù)進(jìn)行交換之后得到的數(shù)組
    int *generateNearlyOrderedArray(int n,int swapTimes)
    {
        //開辟空間后,先生成有序數(shù)組
        int *arr = new int[n];
        for (int i = 0; i < n; i++)
        {
            arr[i] = i;
        }
        srand(time(NULL));
        for (int i = 0; i < swapTimes; i++)
        {
            int posx = rand() % n;
            int posy = rand() % n;
            swap(arr[posx],arr[posy]);
        }
        return arr;
    }

用近乎有序的數(shù)組來測試改進(jìn)后的插入排序算法,其結(jié)果為:

selectionSort:0.161s
insertionSort:0.012s
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

推薦閱讀更多精彩內(nèi)容