# 簡單排序演算法比較 ## 測試環境 | 作業系統 | CPU | RAM | | :--------- | :------------------------------------------------------- | :------ | | Windows 10 | Intel(R) Core(TM) i5-1035G1 <br />CPU @ 1.00GHz 1.19 GHz | 12.0 GB | ## 排序演算法 ### Bubble Sort #### 1.說明 (1)比較相鄰的兩個元素,若前面的元素較大就進行交換。 (2)重複進行(1)的動作直到最後面,最後一個元素將會是最大值。 (3)重複進行(1),(2)的動作,每次比較到上一輪的最後一個元素。 (4)重複進行以上動作直到沒有元素需要比較。 #### 2.圖例 ![](https://i.imgur.com/xMZD4jw.jpg) #### 3.程式碼 ```c void bubble_sort(int a[], int len){ int i, j, temp; for (i=0; i<len-1; i++) { for (j=0; j<len-1-i; j++) if (a[j]>a[j+1]){ temp=a[j]; a[j]=a[j+1]; a[j+1]=temp; } } } ``` ### Selection Sort #### 1.說明 (1)從未排序的數列中找到最小的元素。 (2)將此元素取出並加入到已排序數列最後。 (3)重複以上動作直到未排序數列全部處理完成。 #### 2.圖例 ![](https://i.imgur.com/hWgVvpe.jpg =400x) #### 3.程式碼 ``` c void selection_sort(int a[],int len){ int temp, minIdx; int i, j; for (i=0; i<len-1; i++){ minIdx=i; for (j=i+1; j<len; j++){ if (a[j] < a[minIdx]) minIdx=j; } temp=a[minIdx]; a[minIdx]=a[i]; a[i]=temp; } } ``` ### Insertion Sort #### 1.說明 (1)從未排序數列取出一元素。 (2)由後往前和已排序數列元素比較,直到遇到不大於自己的元素並插入此元素之後;若都沒有則插入在最前面。 (3)重複以上動作直到未排序數列全部處理完成。 #### 2.圖例 ![](https://i.imgur.com/gQFeDUo.png =400x) #### 3.程式碼 ``` c void insertion_sort(int a[], int len){ int i, j, key; for (i=1; i<len; i++) { j=i; key=a[i]; while (j>0 && a[j-1]>key) { a[j]=a[j-1]; j--; } a[j]=key; } } ``` ## 測試資料 ### 建立Data方法及數量 #### 1.說明 (1)於開頭先設定資料大小為1000000 (2)以rand()產生隨機整數 (3)以srand()設定亂數種子,使亂數的數值及序列固定 (4)以迴圈執行將資料存入陣列 #### 2.程式碼 ``` c #include <stdio.h> #include <stdlib.h> #define DATA_CNT 100000 int main(){ int num[DATA_CNT+5]; int i; srand(1); for (i=0; i<DATA_CNT; i++){ num[i]=rand(); printf("%d ", num[i]); } return 0; } ``` ### 將測資存入文件 如下圖,桌面上有名為testdata.c的程式碼檔案,以及編譯出來名為testdata.exe的執行檔 ![](https://i.imgur.com/roSssZM.jpg) 接著,進入cmd(命令提示字元),先cd到存入以上檔案的位置 ![](https://i.imgur.com/fNJfvc6.jpg) 最後,輸入以下指令,檔案位置將會產生所需的測資文字檔 ![](https://i.imgur.com/PMtMuo5.jpg) testdata.txt即為測資文字檔 ![](https://i.imgur.com/A6OWzYn.jpg) ## 測量效能 ### 1.gettimeofday() #### (1)函數原型 \#include <sys/time.h> int gettimeofday(struct timeval*tv,struct timezone *tz ) #### (2)說明 gettimeofday()會把目前的時間用tv 結構回傳,當地時區的訊息則放到tz所指的結構中 #### (3)資料結構 timeval ```c struct timeval{ long tv_sec; //秒 long tv_usec; //微妙 } ``` timezone ```c struct timezone{ int tz_minuteswest; //和greenwich 時間差了多少分鐘 int tz_dsttime; //type of DST correction } ``` 在gettimeofday()函數中tv或者tz都可以為空。如果為空則就不回傳其對應的結構。 ### 2.計算時間差方式 (1)於程式開頭定義兩個timeval,方別為start以及end (2)於進入sort_function()前紀錄一次start的時間 (3)於執行完sort_function()後紀錄一次end的時間 (4)end.tv_sec - start.tv_sec即為兩個時間的"秒數"差(結果為一整數) (5)end.tv_usec - start.tv_usec即為兩個時間的"微秒數"差 (6)可以利用兩者單位換算相加即為start及end的時間差 ### 3.程式碼 ``` c #include <stdio.h> #include <stdlib.h> #define DATA_CNT 100000 int main(){ int num[DATA_CNT+5]; int i; struct timeval start; struct timeval end; unsigned long timer; srand(1); for (i=0; i<DATA_CNT; i++){ num[i]=rand(); } gettimeofday(&start, NULL); sort_function(num,DATA_CNT); gettimeofday(&end, NULL); timer = 1000000*(end.tv_sec-start.tv_sec) + end.tv_usec - start.tv_usec; printf("Sorting performance %ld us (equal %f sec)\n", timer, timer / 1000000.0); return 0; } ``` ## 實驗結果 | 項目 | Bubble Sort | Selection Sort | Insertion Sort | | ----------------- | ------------- | -------------- | -------------- | | 效能(Performance) | 29.875098 sec | 12.535177 sec | 6.721281 sec | | 穩定性(Stability) | Stable | Unstable | Stable | (如果鍵值相同之資料,在排序後相對位置與排序前相同時,稱穩定排序。反之則為不穩定排序) ### 時間複雜度 | | Bubble Sort | Selection Sort | Insertion Sort | | ------------ | ----------- | -------------- | -------------- | | Best Case | O(n) | O(n²) | O(n) | | Worst Case | O(n²) | O(n²) | O(n²) | | Average Case | O(n²) | O(n²) | O(n²) | ### 空間複雜度 | | Bubble Sort | Selection Sort | Insertion Sort | | ---------------- | ----------- | -------------- | -------------- | | Space complexity | O(1) | O(1) | O(1) | ## 結論 1. Bubble Sort只適合處理小型資料,原因是在排序過程中,需要經過非常多次的判斷以及交換,是三種排序法中最沒效率的排序法。 2. 在一般的情況中,Selection Sort交換次數較Bubble Sort少非常多,因此效能比Bubble Sort高非常多。 3. Selection Sort之所以為Unstable的原因是在排序完後,鍵值相同的兩個值先後順序可能換互換。ex: 在i=0時,陣列的值為 5 8 9 5 4 1,因為最小值為1,陣列中第一個5將會與1的位置互換,使得兩個5的前後順序交換。 4. Insertion Sort的判斷次數為三種排序法之中最少的,交換次數也不多,因此為三種排序法中最有效率的排序法。 5. 效能: Insertion Sort > Selection Sort > Bubble Sort #### 參考資料 https://techdemic.com/bubble-sort/ https://studyalgorithms.com/array/selection-sort/ https://www.geeksforgeeks.org/insertion-sort/ https://www.geeksforgeeks.org/selection-sort/ https://www.geeksforgeeks.org/bubble-sort/ https://emn178.pixnet.net/blog/post/93915544 https://emn178.pixnet.net/blog/post/93779892 https://emn178.pixnet.net/blog/post/93791164 https://nosleep.pixnet.net/blog/post/205120138-%E7%A8%8B%E5%BC%8F%E9%96%8B%E7%99%BC-%7C-%5Blinux%5D%5Bc%5D-%E4%BD%BF%E7%94%A8-gettimeofday%28%29-%E5%87%BD%E5%BC%8F%E8%A8%88%E7%AE%97 http://notepad.yehyeh.net/Content/Algorithm/Sort/Sort.php https://www.geeksforgeeks.org/analysis-of-different-sorting-techniques/ http://spaces.isu.edu.tw/upload/18833/3/web/sorting.htm