七種基礎排序算法代碼總彙

一、冒泡排序

算法詳解參考:https://mp.weixin.qq.com/s/wO11PDZSM5pQ0DfbQjKRQAios

#include <iostream>
#include <vector>
using namespace std;

void swap(vector<int> &arr, int i, int j)
{
    int temp = arr[i];
    arr[i] = arr[j];
    arr[j] = temp;
}

void BubbleSort(vector<int> &arr)
{
    int flag = 1;   // flag標記是否繼續比較元素大小,這裏賦值爲1是爲了進入循環
    for(int i = 1; i < arr.size() && flag; i++)
    {
        flag = 0;   // 初始化爲0
        for(int j = arr.size() - 1; j >= i; j--)
        {
            if(arr[j] > arr[j+1])   // 升序
            {
                swap(arr, j+1, j);
                flag = 1;   // 不在比較元素時 flag = 1,進入下一次循環
            }
        }
    }
}

int main()
{
    vector<int> arr = {0, 5, 3, 4, 6, 2};
    BubbleSort(arr);
    for(int i = 0; i < arr.size(); i++)
        cout << arr[i] << " ";
    cout << endl;
    return 0;
}

// 冒泡法排序總時間複雜度 O(n^2)

二、簡單選擇排序

算法詳解參考:https://mp.weixin.qq.com/s/dGfh2t7xhg0wMM_DcYP1Cw算法

#include <iostream>
#include <vector>
using namespace std;

void swap(vector<int> &arr, int i, int j)
{
    int temp = arr[i];
    arr[i] = arr[j];
    arr[j] = temp;
}

void SelectSort(vector<int> &arr)
{
    int min;
    for(int i = 1; i < arr.size(); i++)
    {
        min = i;
        for(int j = i+1; j <= arr.size(); j++)
        {
            if(arr[min] > arr[j])
                min = j;
        }
        if(i != min)
            swap(arr, i, min);
    }
}

int main()
{
    vector<int> arr = {0, 5, 3, 4, 6, 2};
    SelectSort(arr);
    for(int i = 0; i < arr.size(); i++)
        cout << arr[i] << " ";
    cout << endl;
    return 0;
}

// 簡單選擇排序總時間複雜度 O(n^2)
// 性能略優於冒泡

三、直接插入排序

算法詳解參考:https://mp.weixin.qq.com/s/McqFXkXucSZldjU46t5cdw數組

#include <iostream>
#include <vector>

using std::cout;
using std::endl;
using std::vector;

void swap(vector<int> &arr, int i, int j)
{
    int a = arr[i];
    arr[i] = arr[j];
    arr[j] = a;
}

void InsertSort(vector<int> &arr)
{
    for(int i = 1; i < arr.size(); i++)
    {
        int j = i;
        while (j > 0 && arr[j] < arr[j-1])
        {
            swap(arr, j, j-1);
            j--;
        }
        
    }
}

int main()
{
    vector<int> arr = {0, 5, 3, 4, 6, 2};
    InsertSort(arr);
    for(int i = 0; i < arr.size(); i++)
        cout << arr[i] << " ";
    cout << endl;
    return 0;
}

// 直接插入排序總時間複雜度 O(n^2)
// 性能優於冒泡和簡單選擇排序

四、希爾排序

算法詳解參考:https://mp.weixin.qq.com/s/b9-dkpAhWJYshuSs5cwnOw性能

#include <iostream>
#include <vector>
using namespace std;

void ShellSort(vector<int> &arr)
{
    int increment = arr.size();     // 希爾排序的增量初始化
    while (increment > 1)
    {
        increment /= 2;     // 增量折半
        for(int i = 0; i < increment; i++)
        {
            for(int j = i+increment; j < arr.size(); j = j+increment)
            {
                int temp = arr[j];
                int k = 0;
                for(k = j-increment; k >= 0 && arr[k] > temp; k = k-increment)
                    arr[k + increment] = arr[k];    // 因爲 k 的值發生了更新,可是在此循環結束以前索引 j 是沒有發生變化的,因此 k + increment != j(第一次循環時 k+increment = j)
                arr[k + increment] = temp;
            }
        }
    }
}

int main()
{
    vector<int> arr = {5, 8, 6, 3, 9, 2, 1, 7};
    ShellSort(arr);
    for(int i = 0; i < arr.size(); i++)
        cout << arr[i] << " ";
    cout << endl;
    return 0;
}

// 希爾排序是不穩定排序
// Hibbard增量序列:最壞時間複雜度 O(n^(3/2))
// Sedgewick增量序列:最壞時間複雜度 O(n^(4/3))

五、堆排序

算法詳解參考:https://mp.weixin.qq.com/s/8Bid1naBLtEjPoP-R4HkBgui

#include <iostream>
#include <vector>
using namespace std;

// 大頂堆調整
void adjustHeap(vector<int> &arr, int i, int length)
{
    int temp = arr[i];      // 先取出當前元素 i
    for(int k = i*2 + 1; k < length; k = k*2 + 1)   // 從 i 結點左子節點開始,也就是 2i+1 處開始
    {
        if(k+1 < length && arr[k] < arr[k+1])   // 若是左子節點小於右子節點,k指向右子節點
            k++;
        if(arr[k] > temp)   // 若是子節點大於父節點,將子節點賦值給父節點(不用交換)
        {
            arr[i] = arr[k];
            i = k;
        }
        else break;
    }
    arr[i] = temp;  // 將 temp 值放到最終位置
}
// 元素交換
void swap(vector<int> &arr, int i, int j)
{
    int a = arr[i];
    arr[i] = arr[j];
    arr[j] = a;
}

void heapSort(vector<int> &arr)
{
    // 構建大頂堆
    for(int i = arr.size()/2 - 1; i >= 0; i--)
        // 從第一個非葉子結點從上至下,從右到左調整結構
        adjustHeap(arr, i, arr.size());
    // 調整堆結構加交換堆頂元素與末尾元素
    for(int j = arr.size() - 1; j > 0; j--)
    {
        swap(arr, 0, j);        // 將堆頂元素與末尾元素進行交換
        adjustHeap(arr, 0, j); // 從新調整堆結構
    }
}

int main()
{
    vector<int> arr = {5, 8, 6, 3, 9, 2, 1, 7};
    heapSort(arr);
    for(int i = 0; i < arr.size(); i++)
        cout << arr[i] << " ";
    cout << endl;
    return 0;
}

// 堆排序總體時間複雜度 O(nlogn)

六、歸併排序

算法詳解參考:https://mp.weixin.qq.com/s/885uGVhlffWAxjgIEW-TiAspa

#include <iostream>
#include <vector>
using namespace std;

void merge(vector<int> &arr, int start, int mid, int end)
{
    // 開闢額外大集合,設置指針
    vector<int> tempArray((end - start + 1), 0);
    int p1 = start, p2 = mid+1, p = 0;
    // 比較兩個小集合的元素,依次放入大集合
    while(p1 <= mid && p2 <= end)
    {
        if(arr[p1] <= arr[p2])
            tempArray[p++] = arr[p1++];
        else
            tempArray[p++] = arr[p2++];
    }
    // 左(右)側小集合有剩餘,依次放入大集合尾部
    while(p1 <= mid)
        tempArray[p++] = arr[p1++];
    while(p2 <= end)
        tempArray[p++] = arr[p2++];
    // 把大集合元素賦值回原數組
    for(int i = 0; i < tempArray.size(); i++)
        arr[i+start] = tempArray[i];
}

void mergeSort(vector<int> &arr, int start, int end)
{
    if(start < end)
    {
        // 折半成兩個小集合,分別進行遞歸
        int mid = (start + end) / 2;
        mergeSort(arr, start, mid);
        mergeSort(arr, mid+1, end);
        // 把兩個有序小集合歸併成一個大集合
        merge(arr, start, mid, end);
    }
}

int main()
{
    vector<int> arr = {5, 8, 6, 3, 9, 2, 1, 7};
    mergeSort(arr, 0, arr.size() - 1);
    for(int i = 0; i < arr.size(); i++)
        cout << arr[i] << " ";
    cout << endl;
    return 0;
}

// 總時間複雜度 O(nlogn)

七、快速排序

算法詳解參考:https://zhuanlan.zhihu.com/p/93129029指針

// 快排遞歸實現
#include <iostream>
using namespace std;

void quickSort(int *arr, int begin, int end)
{
    if(begin < end)
    {
        int temp = arr[begin];
        int i = begin;
        int j = end;
        while(i < j)
        {
            while(i < j && arr[j] > temp)
                j--;
            arr[i] = arr[j];
            while(i < j && arr[i] <= temp)
                i++;
            arr[j] = arr[i];
        }
        arr[i] = temp;
        // 遞歸排序基準數兩邊子集
        quickSort(arr, begin, i-1);
        quickSort(arr, i+1, end);
    }
    else return;
}
int main()
{
    int num[10] = {23, 14, 5, 7, 29, 50, 11, 33, 10, 8};
    cout << "排序前: " << endl;
    for(int i = 0; i < 10; i++)
        cout << num[i] << " ";
    cout << endl;
    quickSort(num, 0, 9);
    cout << "排序後: " << endl;
    for(int i = 0; i < 10; i++)
        cout << num[i] << " ";
    cout << endl;
    return 0;
}

// 快速排序時間複雜度 O(nlog2N)
相關文章
相關標籤/搜索