排序-radix sort

目錄

1.基本排序  

  2.radix sort  

3.總結         

基本排序-1

氣泡排序法

氣泡排序法 (Bubble sort)

時間複雜度:O(n^2)

氣泡排序的原理是,每回合當前最大的元素都會透過不斷地與其右手邊的元素交換「浮 到」它最終的所在位置,從而在進行 n−1 回合後確定所有元素都已經到達正確的位置。

#include<bits/stdc++.h>
using namespace std;
#define int long long
#define maxn 20005
int arr[maxn],n;
void bubble_sort(){
    for(int i=0;i<n-1;i++){
        for(int j=0;j<n-1;j++){
            if(arr[j]>arr[j+1])swap(arr[j],arr[j+1]);
        }
    }
}
main(){
    while(cin>>n){
        for(int i=0;i<n;i++){
            cin>>arr[i];
        }
        bubble_sort();
        for(int i=0;i<n;i++){
            cout<<arr[i]<<' ';
        }
        cout<<'\n';
    }
}

基本排序-2

選擇排序法

選擇排序法 (Selection sort)

時間複雜度:O(n^2)

首先在未排序序列中找到最小元素,存放到排序序列的起始位置,然後,再從剩餘未排序元素中繼續尋找最小元素,然後放到已排序序列的末尾。 以此類推,直到所有元素均排序完畢。

#include<bits/stdc++.h>
using namespace std;
#define int long long
#define maxn 20005
int arr[maxn],n;
void selection_sort(){
    for(int i=0;i<n-1;i++){
        int mnindex=i;
        for(int j=i+1;j<n;j++){
            if(arr[j]<arr[mnindex])mnindex=j;
        }
        swap(arr[i],arr[mnindex]);
    }
}
main(){
    while(cin>>n){
        for(int i=0;i<n;i++){
            cin>>arr[i];
        }
        selection_sort();
        for(int i=0;i<n;i++){
            cout<<arr[i]<<' ';
        }
        cout<<'\n';
    }
}


基本排序-3

插入排序法

插入排序法 (Insertion

sort)

時間複雜度:O(n^2)

將陣列分成兩堆,

將未排序的序列中的元素插入已排序的序列中

 

網路上的電神講解

#include<bits/stdc++.h>
using namespace std;
#define int long long
#define maxn 20005
int arr[maxn],n;
void insertion_sort(){
    for (int i=1; i<n;i++) {
        int key = arr[i];
        int j=i-1;
        while (key<arr[j] && j>=0) {
            arr[j+1]=arr[j];
            j--;
        }
        arr[j+1]=key;
    }
}
main(){
    while(cin>>n){
        for(int i=0;i<n;i++){
            cin>>arr[i];
        }
        insertion_sort();
        for(int i=0;i<n;i++){
            cout<<arr[i]<<' ';
        }
        cout<<'\n';
    }
}



學到這裡,要怎麼測試code到底對不對呢?

題目:zerojudge a104

排序可不只這些

但其他進階的我放在補充

補充-1

合併排序法 (Merge sort)

時間複雜度:O(n log n)

網路上電神簡報

蔡孟平學長超電簡報

#include<bits/stdc++.h>
using namespace std;
#define int long long
#define maxn 1000005
int arr[maxn],n;
void mergesort(int l,int r){
    if(l==r)return;
    int mid=(l+r)/2;
    mergesort(l,mid);
    mergesort(mid+1,r);
    int n1=mid-l+1,n2=r-mid;
    int L[n1+1],R[n2+1];
    for(int i=0;i<n1;i++)L[i]=arr[l+i];
    for(int i=0;i<n2;i++)R[i]=arr[mid+i+1];
    int x=0,y=0,z=l;
    while(x<n1 && y<n2){
        if(L[x]<R[y]){
            arr[z++]=L[x++];
        }
        else arr[z++]=R[y++];
    }
    while(x<n1)arr[z++]=L[x++];
    while(y<n2)arr[z++]=R[y++];
}
main(){
    int n;
    while(cin>>n){
        for(int i=0;i<n;i++)cin>>arr[i];
        mergesort(0,n-1);
        for(int i=0;i<n;i++)cout<<arr[i]<<' ';
    }
}

補充-2

快速排序法 (Quick sort) 

時間複雜度:期望 O(n log n),最差 O(n^2) 

網路上電神簡報

 

補充-3

C++函式 std::sort 

時間複雜度:最差 O(n log n) 

實作原理:

sort() 底層為 intro sort,是以 Quick Sort 為核心的混合型排序法。

網路上電神簡報


補充

基數排序法

Radix sort

原理

由個位數開始,對所有位數都做一輪排序。每一輪排序只看第 r 位數的大小,以 10 進位整數來說,第 r 位數只有 10 種可能,於是就使用 10 個桶子,並將序列中的數字依照第 r 位數丟進相對應的桶子,再由 0 號桶子開始,將每個桶子中的數字依照放入的順序拿出,形成一個新的序列。由低位數一直做到最高位數,做完後就完成排序了。

例子

26, 15, 27, 35, 17, 36, 28, 16

 

 

 

過程會長怎樣

26, 15, 27, 35, 17, 36, 28, 16

第一輪:從個位數開始挑

                6  ,  5  ,  7 ,  5  , 7 ,  6 ,  8 ,  6

放進0-9的桶子中

     0       1       2       3       4       5       6       7       8       9

15

35

26

36

16

27

17

28

接著依序取出來

     0       1       2       3       4       5       6       7       8       9

15

35

26

36

16

27

17

28

15,35,26,36,16,27,17,28

               15, 35, 26, 36, 16, 27, 17, 28

第二輪:從十位數開始挑

               1  , 3  , 2 ,  3  , 1 ,  2 ,  1 ,  2

放進0-9的桶子中

     0       1       2       3       4       5       6       7       8       9

15

35

26

36

16

27

17

28

第二輪:從十位數開始挑

     0       1       2       3       4       5       6       7       8       9

15

35

26

36

16

27

17

28

一樣 取出來

15,16,17,26,27,28,35,36

這時你會發現

沃 排好了

而且 很快!

分析時間複雜度

若欲排序數字最大為 C,則最多會進行 log C 輪排序,每輪排序需檢查 10 個桶子, 而所有桶子總共有 n 個元素,可以視為 O(10 + n) =O(n),因此總時間複雜度為 O(n log C)。

從剛剛的排序過程發現了什麼

從個位數開始?

他只能排序整數

更準確來說

是任何可以按位比較且位數足夠少的資料型態,例如長度相同的字串也可以。 

優點 缺點
時間複雜度 在特定條件下可達 O(nk),比 O(n log n) 更快 當數據範圍大時,k 變大,時間複雜度上升
額外空間需求 可使用桶排序,對於大規模數據表現良好 需要額外的桶來存儲數據,空間複雜度為 O(n + k),比原地排序(如 Quick Sort)的 O(1) 或 O(log n) 高
特殊場景表現 適合數據範圍小但數量大的情境,如 100 萬個 6 位數字 當數據範圍極大(如 64-bit 數字),可能不如 Quick Sort 或 Merge Sort 高效

code

#include<bits/stdc++.h>
using namespace std;
#define int long long
#define maxn 2000005
int arr[maxn],n;
void radix_sort(){
    vector<int>bucket[10];
    for(int radix=1,r=0;r<15;radix*=10,r++){
        for(int i=0;i<10;i++)bucket[i].clear();
        for(int i=0;i<n;i++){
            int d=(arr[i]/radix)%10;
            bucket[d].push_back(arr[i]);
        }

        int len=0;
        for(int i=0;i<10;i++){
            for(int j=0;j<bucket[i].size();j++){
                arr[len++]=bucket[i][j];
            }
        }
    }
}
main(){
    while(cin>>n){
        for(int i=0;i<n;i++){
            cin>>arr[i];
        }
        radix_sort();
        for(int i=0;i<n;i++){
            cout<<arr[i]<<' ';
        }
        cout<<'\n';
    }
}




總結

考試的時候怎麼可能手刻

一個排序(通常)

所以我最推薦std::sort

一行簡單明瞭

時間複雜度也不錯

那學前面那些有什麼用?

好處 說明 範例
理解演算法分析 學習時間與空間複雜度,提升分析能力 O(n²) vs O(n log n)
提升程式設計能力 熟悉遞迴(分治演算法)、優化技巧 Quick Sort(遞迴)、Bubble Sort 優化
打好資料結構基礎 排序與二元搜尋樹、堆積、佇列等結構相關 Heap Sort(優先佇列)、BST(排序輸出)
競賽與考試準備 許多競程與考試會考排序相關問題 資訊之芽預試

下課

有講錯的歡迎電我

排序-radix sort

By wuchanghualeo

排序-radix sort

  • 63