冒泡排序:它重复地走访过要排序的数列,一次比较两个元素,如果他们的顺序错误,就把他们交换过来。走访数列的工作是重复地进行直到没有再需要交换的,即该数列排序完成。这个算法的名字由来是因为越大的元素经过交换慢慢“浮到”数列的顶端,故称冒泡排序。
算法原理
1.比较相邻的元素。如果第一个比第二个大,就交换他们两个。
2.对每一对相邻元素做同样的工作,从开始的第一对,到结尾的最后一对。在这一点,最后的元素应该是最大的数。
3.针对所有元素重复以上的步骤,除了最后一个。
4.持续每一对越来越少的元素重复上面的步骤,直到没有任何一对数字需要比较。
2.对每一对相邻元素做同样的工作,从开始的第一对,到结尾的最后一对。在这一点,最后的元素应该是最大的数。
3.针对所有元素重复以上的步骤,除了最后一个。
4.持续每一对越来越少的元素重复上面的步骤,直到没有任何一对数字需要比较。
简单的冒泡排序:
#include<stdio.h> void bubble_sort(int arr[], int sz) { int i = 0; int j = 0; int tmp = 0; for (i = 0; i < sz - 1; i++) { for (j = 0; j < sz - i - 1; j++) { if (arr[j] > arr[j + 1]) { tmp = arr[j]; arr[j] = arr[j + 1]; arr[j + 1] = tmp; } } } } void print_arr(int arr[], int sz) { int i = 0; for (i = 0; i < sz; i++) { printf("%d ", arr[i]); } } int main() { int arr[10] = { 1, 4, 6, 7, 8, 9, 5, 3, 10, 2 }; int sz = sizeof(arr) / sizeof(arr[0]); bubble_sort(arr, sz); print_arr(arr, sz); return 0; }
在这里有两个要点:
1.使用嵌套的for循环来控制
2.如果满足条件进行交换
对于这种方法,会效率比较低下,如果后面的数据已经排好序,但是程序还是会进行判断,所以,我们可以实现优化。
优化方法:
#include<stdio.h> void bubble_sort(int arr[], int sz) { int i = 0; int j = 0; int tmp = 0; int flag = 1; for (i = 0; i < sz - 1 && flag; i++) { flag = 0; //设置一个标志变量,如果数据顺序没有变化,那么结束程序 for (j = 0; j < sz - i - 1; j++) { if (arr[j] > arr[j + 1]) { flag = 1; tmp = arr[j]; arr[j] = arr[j + 1]; arr[j + 1] = tmp; } } } } void print_arr(int arr[], int sz) { int i = 0; for (i = 0; i < sz; i++) { printf("%d ", arr[i]); } } int main() { int arr[10] = { 1, 4, 2, 3, 5, 6, 7, 8, 9, 10 }; int sz = sizeof(arr) / sizeof(arr[0]); bubble_sort(arr, sz); print_arr(arr, sz); return 0; }
使用指针的方法:
void print_arr(int arr[], int sz) { int i = 0; for (i = 0; i < sz; i++) { printf("%d ", arr[i]); } } void bubble_sort(int * arr, int sz) { int * start = arr; int * end = arr + sz - 1; int tmp; for (start = arr; start < end; end--) { //使用一个临时指针来实现相邻元素的交换 int * cur = start; for (cur = start; cur < end; cur++) { if (*cur > *(cur + 1)) { tmp = *cur; *cur = *(cur + 1); *(cur + 1) = tmp; } } } } int main() { int arr[10] = { 1, 4, 6, 7, 8, 9, 5, 3, 10, 2 }; int sz = sizeof(arr) / sizeof(arr[0]); bubble_sort(arr, sz); print_arr(arr, sz); return 0; }
这里的解释图如下:
经过一趟循环之后,实现end--,而且cur要回到起始的地址。
扫描二维码关注公众号,回复:
1069384 查看本文章
模拟实现一个通用的冒泡排序:
在这里,我们通过学习qsort(快速排序)来实现。
qsort利用两个函数:
1.显示函数:来接收各种类型的数据,其中比较函数的地址是此函数的一个参数
2.比较函数:得自己来实现各种比较函数。
void qsort(void *base, size_t num, size_t width, int(__cdecl *compare)(const void *elem1, const void *elem2));
参数解释:
base:目标数组的起始地址
num:数组中元素的个数
width:元素大小
函数指针:函数的参数为void *,使得数组和字符串也能被使用。
#include<stdio.h> #include<assert.h> int cmp_int(const void * e1, const void * e2) //强制类型转换并解引用可以得到两个元素 { return *(int *)e1 - *(int *)e2 ; } void print_arr(int arr[], int sz) { int i = 0; for (i = 0; i < sz; i++) { printf("%d ", arr[i]); } printf("\n"); } void Swap(char * buf1, char * buf2, int width) { int i = 0; char tmp; assert(buf1&&buf2); for (i = 0; i < width; i++) { tmp = *buf1; *buf1 = *buf2; *buf2 = tmp; buf1++; //一个字节一个字节的交换 buf2++; } } void bubble_sort(void * base, int sz, int width, int(*cmp)(void * e1, void * e2)) { int i = 0; int j = 0; assert(base&&cmp); for (i = 0; i < sz - 1; i++) { for (j = 0; j < sz - i - 1; j++) { //要拿到两个元素的地址 if (cmp(((char *)base + width*j), (char *)base + width*(j+1))>0) { //交换 Swap(((char *)base + width*j), (char *)base + width*(j + 1), width); } } } } int main() { int arr[10] = { 1, 2, 4, 7, 8, 0, 9, 5, 6, 3 }; int sz = sizeof(arr) / sizeof(arr[0]); bubble_sort(arr, sz, sizeof(arr[0]), cmp_int); print_arr(arr, sz); return 0; }
下面是运算结果图: