逐個比較相鄰元素,若是逆序則交換。每一趟都會讓一個元素就位,總共比較 n-1 趟。web
n 個元素,須要進行 n - 1 輪冒泡,每次冒泡都會有一個元素就位,因此每輪冒泡的循環次數都會減一。時間複雜度爲:
1 + 2 + … + n-1 = n(n-1)/2 = O(n^2)svg
初始值: 5 4 3 2 1 首輪冒泡: 4 3 2 1 5 最後一個元素就位 第二輪: 3 2 1 4 5 倒數第二個元素就位 ...
// 冒泡排序,每輪都會排好一個元素 void bubbleSort(int arr[], int count) { int i, j; // n 個元素,須要比較 n-1 輪 for (i = count - 1; i > 0; i--) { // 每輪比較,只需在剩餘的 j 個元素中,從頭開始比較 j-1 次 for (j = 1; j <= i; j++) { if (arr[j-1] > arr[j]) { swap(arr, j - 1, j); } } } }
上面的冒泡排序,即便剩餘元素都已經有序,內層 for 循環中沒有發生元素交換,也會繼續執行下去。能夠設置一個值,在剩餘元素都已經就位時提早結束循環:spa
void bubbleSort(int arr[], int count) { int i, j, sorted; // n 個元素,須要比較 n-1 輪 for (i = count - 1; i > 0; i--) { sorted = 1; // 每輪比較,只需在剩餘的 j 個元素中,從頭開始比較 j-1 次 for (j = 1; j <= i; j++) { if (arr[j-1] > arr[j]) { swap(arr, j - 1, j); sorted = 0; } } if (sorted == 1) { break; } } }
對於 5 4 3 2 1 9 6 7 8
這樣的數據,第一輪排序以後,最後的部分元素都會就位,而不是僅僅就位一個元素。若是每次都標記有序的區間,也能夠改善冒泡排序的效率:code
void bubbleSort(int arr[], int count) { int i, j; int last = count - 1; for (i = count - 1; i > 0; i--) { i = last; for (j = 1; j <= i; j++) { if (arr[j-1] > arr[j]) { swap(arr, j-1, j); last = j; } } } }
冒泡排序每次相鄰元素的比較,均可能會發生元素的交換。若是在一輪掃描中,只記錄最大元素的位置,掃描結束後再判斷是否交換,能夠略微改善效率。xml
選擇排序,就是冒泡排序的簡單改進版,每輪掃描都會選擇一個最大元素,若是這個最大元素未就位,則交換。排序
代碼:token
// 選擇排序,每輪的比較次數跟冒泡同樣,但交換次數最多一次 void selectionSort(int arr[], int count) { int i, j, key; for (i = count-1; i > 0; i--) { key = 0; for (j = 1; j <= i; j++) { if (arr[j] > arr[key]) { key = j; } } if (i != key) { swap(arr, i, key); } } }
玩撲克牌的時候,咱們會把手裏的牌排好次序。每次摸一張牌,都會插入到合適的位置。插入排序,就是這個意思。string
首先咱們把待排序的元素的第一個元素看做有序集合中僅有的元素,而後把第二個元素插入到這個集合的合適位置,而後是第三個,以此類推。it
代碼執行時,仍然是逐個相鄰元素進行比較。每次發現逆序對,就開始執行插入操做,設逆序對前一個元素是 x,後一個元素是 y:io
代碼:
// 插入排序,只掃描一輪,只要有逆序對,就將逆序對的後者與以前的元素 // 逐個比較,直到不逆序或越界。將這些元素逐個後移一位,而後插入這個元素 void insertSort(int arr[], int count) { int i, j, tmp; for (i = 1; i < count; i++) { if (arr[i-1] > arr[i]) { tmp = arr[i]; j = i - 1; while(j >= 0 && arr[j] > tmp) { arr[j+1] = arr[j]; j--; } arr[j+1] = tmp; } } }
#include <stdio.h> void swap(int arr[], int i, int j) { int tmp = arr[i]; arr[i] = arr[j]; arr[j] = tmp; } // 冒泡排序,每輪都會排好一個元素 void bubbleSort(int arr[], int count) { int i, j; // n 個元素,須要比較 n-1 輪 for (i = count - 1; i > 0; i--) { // 每輪比較,只需在剩餘的 j 個元素中,從頭開始比較 j-1 次 for (j = 1; j <= i; j++) { if (arr[j-1] > arr[j]) { swap(arr, j - 1, j); } } } } // 選擇排序,每輪的比較次數跟冒泡同樣,但交換次數最多一次 void selectionSort(int arr[], int count) { int i, j, key; for (i = count-1; i > 0; i--) { key = 0; for (j = 1; j <= i; j++) { if (arr[j] > arr[key]) { key = j; } } if (i != key) { swap(arr, i, key); } } } // 插入排序,只掃描一輪,只要有逆序對,就將逆序對的後者與以前的元素 // 逐個比較,直到不逆序或越界。將這些元素逐個後移一位,而後插入這個元素 void insertSort(int arr[], int count) { int i, j, tmp; for (i = 1; i < count; i++) { if (arr[i-1] > arr[i]) { tmp = arr[i]; j = i - 1; while(j >= 0 && arr[j] > tmp) { arr[j+1] = arr[j]; j--; } arr[j+1] = tmp; } } } int main(void) { int arr[10] = {2, 8, 1, 5, 3, 0, 4, 9, 7, 6}; int count = 10; int i; printf("raw:\t"); for (i = 0; i < 10; i++) { printf("%d ", arr[i]); } // printf("\nbubble:\t"); // bubbleSort(arr, count); // for (i = 0; i < 10; i++) { // printf("%d ", arr[i]); // } // printf("\nselect:\t"); // selectionSort(arr, count); // for (i = 0; i < 10; i++) { // printf("%d ", arr[i]); // } printf("\ninsert:\t"); insertSort(arr, count); for (i = 0; i < 10; i++) { printf("%d ", arr[i]); } return 0; }