1. 程式人生 > >排序【1】插入排序

排序【1】插入排序

常見排序

在實際生活中,排序的運用很多,排序就是將一組雜亂無章的資料升序或者降序排成有序的序列。常見的排序演算法有。這裡寫圖片描述
不同的排序演算法適用於不同的場景下,衡量一個排序演算法的標準不僅有空間複雜度,空間複雜度,還有穩定性。一個穩定的排序演算法,相同的排序碼在排序前後相對位置是不會發生變化的。
當然,排序也會根據資料量的情況,分為:
1.內部排序:資料可以載入到記憶體中進行排序。
2.外部排序:資料元素太多不能一次性載入到記憶體中,根據排序的情況不能再記憶體和外村中移動資料的排序。

插入排序

演算法思想:每一步把一個元素key根據其排序碼插入到它前面的一組已經排好序的序列中,直到所有元素排好序。
這裡寫圖片描述


具體執行步驟:
(1)先認為第一個元素是已序的,第二個元素。
(2)去第二個元素,從後向前在已序的序列中比較。
(3)如果該元素比(已排序)比新元素大,將該元素移動到下一個位置。
(3)重複步驟三,直到找到比已排序元素小或者等於的元素。
(4)插入新元素到該位置。
(5)重複步驟(2)
演算法效能
時間複雜度:
最優的情況下:就是資料元素已經是升序的,時間複雜度O(N);
最差的情況:資料序列是降序的,時間複雜度O(N^2);
空間複雜度:O(1)
穩定性:穩定。
適用的場景:當資料是已序的或者接近有序的,並且資料量比較小。
程式碼實現:

//最差的情況是降序拍,時間複雜度O(N^2)
//最好的情況是升序的,時間複雜度是O(N)
//平均時間複雜度O(N^2)
//穩定的排序演算法。
//空間複雜度O(1)
void InsertSort(int *array,int size)
 {
    for (int i=1;i<size;i++)
    {
        int end = array[i];
        int j = i - 1;
        while (j >= 0 && array[j] > end)//找到帶    c插入元素位置
        {
            array
[j + 1] = array[j]; j--; } array[j + 1] = end; } }

我們可以用二分查詢來提高查詢插入位置的位置,來對插入排序進行優化,簡稱二分插入排序。
實現程式碼:

void BinaryInsertSort(int*array, int size)
{
    for (int i = 1; i < size; ++i)
    {
        int left = 0;
        int right = i - 1;
        int end = array[i];
        while (left<= right)    
        {
            int mid = left + ((right - left) >> 1);
            if (array[mid] < end)
            {
                left = mid + 1;
            }
            else
            {
                right = mid - 1;
            }

        }
        for (int j = i - 1; j >= left; --j)
        {
            array[j + 1] = array[j];
        }
        array[left] = end;


    }


}

希爾排序 (減增量排序)

從本質上來說,希爾排序是對直接插入排序的一種優化,為了避免直接插入排序出現最差的情況,希爾排序將資料元素進行了分組,先進行預排序,使資料逐漸接近有序,再使用插入排序。
基本思想:先將待排序序列分割成若干個子序列(子序列由相隔某個“增量”的元素組成),分別對這些子序列進行直接插入排序,然後減小“增量”,分組排序子序列,使序列 基本有序,最後再對全體元素進行一次直接插入排序。
這裡寫圖片描述
適用場景:希爾排序是對插入排序的一種優化,當資料元素比較多時,適合希爾排序。
時間複雜度:當N比較大的時候,時間複雜度在O(N^1.25)-1.6O(N……1.25)之間
空間複雜度:O(1)
穩定性:不穩定
程式碼實現:

void ShellSort(int*array, int size)
{
    assert(array);
    int gap = 1;
    while (gap < size)
    {
        gap = gap * 2 + 1;
    }
    while (gap>=0)
    {
        for (int i = gap; i < size; ++i)
        {
            int key = array[i];
            int j = i - gap;
            while (j>0&&key<array[j])
            {
                array[j + 1] = array[j];
                j = j - gap;

            }
            array[j + gap] = key;
        }
        gap = gap / 3 + 1;
    }