# 計概排序演算法報告
==11228210 黃科傑==
# 氣泡排序法
## ==THEORY==
氣泡排序(Bubble Sort)是一種簡單的排序算法,它會多次遍歷要排序的數列,每次遍歷時,相鄰的兩個元素進行比較,如果它們的順序錯誤就交換它們,直到沒有任何相鄰元素需要交換為止。這樣,最大(或最小)的元素就像氣泡一樣逐漸浮到了數列的頂端(或底端)。因此得名。
## ==EXAMPLE==
```
#include <stdio.h>
void swap(int *xp, int *yp) {
int temp = *xp;
*xp = *yp;
*yp = temp;
}
void bubbleSort(int arr[], int n) {
int i, j;
for (i = 0; i < n-1; i++) {
for (j = 0; j < n-i-1; j++) {
if (arr[j] > arr[j+1]) {
swap(&arr[j], &arr[j+1]);
}
}
}
}
int main() {
int arr[] = {64, 34, 25, 12, 22, 11, 90};
int n = sizeof(arr)/sizeof(arr[0]);
for (int i = 0; i < n; i++)
printf("%d ", arr[i]);
printf("\n");
bubbleSort(arr, n);
for (int i = 0; i < n; i++)
printf("%d ", arr[i]);
printf("\n");
return 0;
}
```
## ==TIMER==
1. ==0.144s==
2. ==0.165s==
3. ==0.141s==
## ==COMPARISON==
對於小型數據集,氣泡排序的執行時間通常很短。但隨著數據量的增加,特別是在處理大型數據時,氣泡排序的效率會顯著下降。
# 插入排序
## ==THEORY==
插入排序(Insertion Sort)是一種簡單直觀的排序演算法,其原理是將未排序的元素逐個插入到已排序序列中的合適位置。插入排序從第二個元素開始,將該元素與已排序的子序列進行比較並插入到正確的位置,直到所有元素都被排序完成。
## ==EXAMPLE==
```
#include <stdio.h>
void insertionSort(int arr[], int n) {
int i, key, j;
for (i = 1; i < n; i++) {
key = arr[i];
j = i - 1;
while (j >= 0 && arr[j] > key) {
arr[j + 1] = arr[j];
j = j - 1;
}
arr[j + 1] = key;
}
}
int main() {
int arr[] = {64, 34, 25, 12, 22, 11, 90};
int n = sizeof(arr) / sizeof(arr[0]);
insertionSort(arr, n);
for (int i = 0; i < n; i++)
printf("%d ", arr[i]);
printf("\n");
return 0;
}
```
## ==TIMER==
1. ==0.065s==
2. ==0.052s==
3. ==0.082s==
## ==COMPARISON==
對於小型數據集,插入排序執行時間通常很短。但隨著數據量增加,執行時間會線性增長,尤其在大型數據集上表現較差。
# 合併排序
## ==THEORY==
合併排序(Merge Sort)是一種分治算法,其核心思想是將一個數組分成兩個子數組,對每個子數組進行遞歸排序,然後將兩個已排序的子數組合併為一個有序數組。合併排序的時間複雜度為O(n log n),其中n是要排序的元素數量。
## ==EXAMPLE==
```
#include <stdio.h>
#include <stdlib.h>
void merge(int arr[], int l, int m, int r) {
int i, j, k;
int n1 = m - l + 1;
int n2 = r - m;
int L[n1], R[n2];
for (i = 0; i < n1; i++)
L[i] = arr[l + i];
for (j = 0; j < n2; j++)
R[j] = arr[m + 1 + j];
i = 0;
j = 0;
k = l;
while (i < n1 && j < n2) {
if (L[i] <= R[j]) {
arr[k] = L[i];
i++;
} else {
arr[k] = R[j];
j++;
}
k++;
}
while (i < n1) {
arr[k] = L[i];
i++;
k++;
}
while (j < n2) {
arr[k] = R[j];
j++;
k++;
}
}
void mergeSort(int arr[], int l, int r) {
if (l < r) {
int m = l + (r - l) / 2;
mergeSort(arr, l, m);
mergeSort(arr, m + 1, r);
merge(arr, l, m, r);
}
}
int main() {
int arr[] = {64, 34, 25, 12, 22, 11, 90};
int n = sizeof(arr) / sizeof(arr[0]);
mergeSort(arr, 0, n - 1);
for (int i = 0; i < n; i++)
printf("%d ", arr[i]);
printf("\n");
return 0;
}
```
## ==TIMER==
1. ==0.032s==
2. ==0.030s==
3. ==0.034s==
## ==COMPARISION==
合併排序的執行時間較穩定,其時間複雜度為O(n log n)。對於任意大小的數組,合併排序的執行時間都相對較長,但相對於其他複雜度相同的排序算法,它的性能通常更好。
# 選擇排序
## ==THEORY==
選擇排序(Selection Sort)是一種簡單直觀的排序算法,其原理是每次選擇待排序數組中的最小元素,並將其放置在已排序部分的末尾。選擇排序的時間複雜度為O(n^2),其中n是要排序的元素數量。
## ==EXAMPLE==
```
#include <stdio.h>
void swap(int *xp, int *yp) {
int temp = *xp;
*xp = *yp;
*yp = temp;
}
void selectionSort(int arr[], int n) {
int i, j, min_idx;
for (i = 0; i < n-1; i++) {
min_idx = i;
for (j = i+1; j < n; j++) {
if (arr[j] < arr[min_idx]) {
min_idx = j;
}
}
swap(&arr[min_idx], &arr[i]);
}
}
int main() {
int arr[] = {64, 34, 25, 12, 22, 11, 90};
int n = sizeof(arr) / sizeof(arr[0]);
selectionSort(arr, n);
for (int i = 0; i < n; i++)
printf("%d ", arr[i]);
printf("\n");
return 0;
}
```
## ==TIMER==
1. ==0.111s==
2. ==0.102s==
3. ==0.104s==
## ==COMPARISON==
選擇排序的執行時間較慢,其時間複雜度為O(n^2)。對於小型數據集,選擇排序的執行時間可能還可以接受,但隨著數據量的增加,其執行時間會快速增長,尤其是在大型數據集上表現較差。相較於其他排序算法,如快速排序和合併排序,選擇排序的效率較低。
# 整數排序-快速排序
## ==THEORY==
快速排序是一種基於分治思想的排序算法,它通過選擇一個基準元素,將數組分割成兩個子數組,並遞歸地對子數組進行排序。它的平均時間複雜度為O(n log n),但在最壞情況下可能達到O(n^2)。
## ==EXAMPLE==
```
#include <stdio.h>
void swap(int* a, int* b) {
int t = *a;
*a = *b;
*b = t;
}
int partition(int arr[], int low, int high) {
int pivot = arr[high];
int i = (low - 1);
for (int j = low; j <= high - 1; j++) {
if (arr[j] < pivot) {
i++;
swap(&arr[i], &arr[j]);
}
}
swap(&arr[i + 1], &arr[high]);
return (i + 1);
}
void quickSort(int arr[], int low, int high) {
if (low < high) {
int pi = partition(arr, low, high);
quickSort(arr, low, pi - 1);
quickSort(arr, pi + 1, high);
}
}
int main() {
int arr[] = {10, 7, 8, 9, 1, 5};
int n = sizeof(arr) / sizeof(arr[0]);
quickSort(arr, 0, n - 1);
for (int i = 0; i < n; i++)
printf("%d ", arr[i]);
printf("\n");
return 0;
}
```
## ==TIMER==
1. ==0.042s==
2. ==0.036s==
3. ==0.043s==
## ==COMPARISON==
快速排序的執行時間取決於輸入數據的規模和特性。通常情況下,快速排序的時間複雜度為O(n log n),但在最壞情況下可能達到O(n^2)。對於隨機或近似隨機的數據,快速排序通常表現良好並具有較短的執行時間,但在某些情況下,可能需要考慮其他排序算法以避免最壞情況的發生。
# 心得
這次藉由撰寫排序演算法報告,讓我學習如何寫出排序N個數的程式,以及學習如何讓程式輸出運行時間,除了上課老師教的4種排序法外,還找到快速排序法,其運行時間在小數據極為出色,遠超其他排序法,讓我反思,生活中不應該只侷限一種方法,可以多查詢、嘗試新的方式,或許會有預料之外的結果。