逐个比较相邻元素,若是逆序则交换。每一趟都会让一个元素就位,总共比较 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; }