O(n^2)的排序演算法

廣海_小瘋瘋丶發表於2018-01-13

O(n^2)的排序演算法

  • O(n^2)是比較基礎的排序演算法,效率較低,編碼簡答,易於實現,是一些簡單情景的首選。
  • 在一些特殊的情況下,簡單的排序演算法更有效
  • 簡單的排序演算法思想衍生出複雜的排序演算法
  • 作為子過程,改進更復雜的排序演算法

選擇排序 Selection Sort

需要將下列數從小到大排列

在這裡插入圖片描述

從第一個開始排,找到比第一個(8)後面最小的數,是1

在這裡插入圖片描述

然後將其交換位置

在這裡插入圖片描述

此時的1就是最終排序的位置

在這裡插入圖片描述

後面的依次類推

在這裡插入圖片描述
在這裡插入圖片描述

C++程式碼實現

#include <iostream>
#include <algorithm>

using namespace std;

void selectionSort(int arr[], int n){

    for(int i = 0 ; i < n ; i ++){
        // 尋找[i, n)區間裡的最小值
        int minIndex = i;
        for( int j = i + 1 ; j < n ; j ++ )
            if( arr[j] < arr[minIndex] )
                minIndex = j;
		//與最小值交換位置
        swap( arr[i] , arr[minIndex] );
    }

}

int main() {
	//硬生成序列
    int a[10] = {10,2,5,7,9,3,4,8,6,1};
    selectionSort(a,10);
    for( int i = 0 ; i < 10 ; i ++ )
        cout<<a[i]<<" ";
    cout<<endl;

    return 0;
}

稍加改造一下函式,使其對各種型別都通用

#include <iostream>
#include <string>

using namespace std;

template<typename T>
void selectionSort(T arr[], int n){

    for(int i = 0 ; i < n ; i ++){

        int minIndex = i;
        for( int j = i + 1 ; j < n ; j ++ )
            if( arr[j] < arr[minIndex] )
                minIndex = j;

        swap( arr[i] , arr[minIndex] );
    }
}

int main() {

    // 測試模板函式,傳入整型陣列
    int a[10] = {10,9,8,7,6,5,4,3,2,1};
    selectionSort( a , 10 );
    for( int i = 0 ; i < 10 ; i ++ )
        cout<<a[i]<<" ";
    cout<<endl;

    // 測試模板函式,傳入浮點數陣列
    float b[4] = {4.4,3.3,2.2,1.1};
    selectionSort(b,4);
    for( int i = 0 ; i < 4 ; i ++ )
        cout<<b[i]<<" ";
    cout<<endl;

    // 測試模板函式,傳入字串陣列
    string c[4] = {"D","C","B","A"};
    selectionSort(c,4);
    for( int i = 0 ; i < 4 ; i ++ )
        cout<<c[i]<<" ";
    cout<<endl;
    return 0;
}

結果:1 2 3 4 5 6 7 8 9 10

1 2 3 4 5 6 7 8 9 10
1.1 2.2 3.3 4.4
A B C D

插入排序 Insert Sort

雖然作為O(n^2)的排序演算法,但在陣列近乎有序的情況下,它的排序效率及其的高,甚至比O(nlogn)的演算法效率還要高,可以作為複雜演算法中的子過程。

需要將下列數從小到大排列

在這裡插入圖片描述

先將第二個數(6)與前面的數相比較,小的話就交換位置

在這裡插入圖片描述

然後再看第三個數(2)跟前面的數相比較,2<8,所以交換位置,再繼續跟前面的數(6)比較,2<6,所以繼續交換位置

在這裡插入圖片描述
在這裡插入圖片描述
在這裡插入圖片描述

後面的依次類推

C++程式碼實現

template<typename T>
void insertionSort(T arr[], int n){

    for( int i = 1 ; i < n ; i ++ ) {

        // 尋找元素arr[i]合適的插入位置
        // 寫法1
//        for( int j = i ; j > 0 ; j-- )
//            if( arr[j] < arr[j-1] )
//                swap( arr[j] , arr[j-1] );
//            else
//                break;

        // 寫法2
        for( int j = i ; j > 0 && arr[j] < arr[j-1] ; j -- )
            swap( arr[j] , arr[j-1] );

    }

    return;
}

改進版的插入排序

由於前面的插入排序一個swap需要經過三步,效率不是很高,以下是改進版的插入排序演算法,不使用swap進行交換,而是通過先將數複製下來,再與前面的進行比對,總體思想是一樣的。

先把第二個數(6)複製一份,先看看它適不適合放在當前位置,讓6跟前面的數(8)作比較,因為6<8,所以顯然不適合當前位置,而8適合當前位置。

在這裡插入圖片描述

把6往後移,因為是第一個元素了,所以直接把6放在這個位置

在這裡插入圖片描述
在這裡插入圖片描述

後面依次類推

C++程式碼實現

void insertionSort(T arr[], int n){

    for( int i = 1 ; i < n ; i ++ ) {
        // 寫法3
        T e = arr[i];
        int j; // j儲存元素e應該插入的位置
        for (j = i; j > 0 && arr[j-1] > e; j--)
            arr[j] = arr[j-1];
        arr[j] = e;
    }

相關文章