一、前言
在对一组数组进行排序是,我们经常用到冒泡排序,它是一种较简单的排序算法。
冒泡排序的原理如下:
- 比较相邻的两个元素。如果第一个比第二个大,就交换它们两个。
- 对每一对相邻元素做同样的工作,从开始第一对到结尾的最后一对。在这一点,最后的元素应该会是最大的数。
- 针对所有的元素重复以上的步骤,除了最后一个。
- 持续每次对越来越少的元素重复上面的步骤,直到没有任何一对数字需要比较。
根据上图可以发现:n个元素的比较,需要n-1趟;每一趟比较的次数n-趟数。
通常我们会针对某一种类型实现一个冒泡排序,示例:
#include <stdio.h>void Bubble_Sort_Int(int* arr, int len)
{for (int i = len - 1; i > 0; i--){for (int j = 0; j < i; j++){if (arr[j] > arr[j + 1]){int tmp = arr[j];arr[j] = arr[j + 1];arr[j + 1] = tmp;}}}
}int main()
{int arr[] = {4,5,2,6,9,2,0};int len = sizeof(arr)/sizeof(*arr);Bubble_Sort_Int(arr, );return 0;
}
但是上面的代码存在一个问题,就是只能排序整形数据。如果我们想把一个浮点型、字符串等其他类型也进行排序,显然这套代码是不适用的。那有没有一种能够排序任何数据的算法呢?
二、设计思路
在此之前,我们先看C语言的一个库函数qsort():
void qsort(void* ptr, size_t count, size_t size, int (*comp)(const void*, const void*)); /*
作用:把一组数据以快速排序的方式升序排列。
参数: 1. ptr - 指向待排序的数组的指针。 2. count - 数组的元素数目。 3. size - 数组每个元素的字节大小。 4. comp - 比较函数。若首个参数小于第二个,则返回负整数值,若首个参数大于第二个,则返回正整数值,若两参数等价,则返回零。该函数需要使用者自己实现。
*/
代码示例:
int cmp_int(const void* p1, const void* p2)
{return *(int*)p1 - *(int*)p2;
}
int main()
{int arr[] = { 4,5,2,6 };int len = sizeof(arr) / sizeof(*arr);qsort(arr, len, sizeof(*arr), cmp_int);return 0;
}
那么我们也可以模拟实现一个qsort函数,但是采用冒泡排序的方式实现。
三、代码实现
#include <stdio.h>
#include <string.h>//交换两个元素 - p1和p2是两个元素的起始地址,size是每个元素的大小
void Swap(char* p1, char* p2, size_t size)
{//将每一个字节进行交换for (int i = 0; i < size; i++){char tmp = *(p1 + i);*(p1 + i) = *(p2 + i);*(p2 + i) = tmp;}
}//通用的冒泡排序算法(升序)
void Bubble_Qsort(void* ptr, size_t count, size_t size, int (*comp)(const void*, const void*))
{//交换的趟数for (int i = 0; i < count - 1; i++){//每一趟每个元素的交换for (int j = 0; j < count - 1 - i; j++){/*为什么要把ptr转换成char*类型?因为我们并不知道这是一个什么类型的数据,也就不知道一次能访问多少个字节,如果我们把它转换成char*类型,再解引用,就可以操作一个字节。*/if (comp((char*)ptr + j*size, (char*)ptr + (j+1)*size) > 0){Swap((char*)ptr + j * size, (char*)ptr + (j + 1) * size, size);}}}
}
int cmp_int(const void* p1, const void* p2)
{return *(int*)p1 - *(int*)p2;//如果它们的差大于零,说明p1大于p2
}
int cmp_str(const void* p1, const void* p2)
{return strcmp((char*)p1, (char*)p2);
}
int main()
{//定义两个需要排序的数组int arr[] = { 4,5,2,6,9,2,0 };char str[] = "dcbaaaaa";//计算arr数组的元素个数int len = sizeof(arr) / sizeof(*arr);//调用排序函数Bubble_Qsort(str, strlen(str), sizeof(*str), cmp_str);Bubble_Qsort(arr, len, sizeof * arr, cmp_int);//打印排序后的元素printf("%s\n", str);for (int i = 0; i < len; i++){if (arr[i] != 0){printf("%d ", arr[i]);}}return 0;
}
输出结果:
ps:如有问题或想法欢迎在讨论区讨论。