1.冒泡排序
前面我们学习过冒泡排序
现在来回顾一下
#include <stdio.h>
void bubble_sort(int arr[], int sz);
void arr_printf(int arr[], int sz);
int main()
{
int arr[] = { 10,9,8,7,6,5,4,3,2,1 };
int sz = sizeof(arr) / sizeof(arr[0]);
bubble_sort(arr, sz);
arr_printf(arr, sz);
return 0;
}
void bubble_sort(int arr[],int sz)
{
for (int i = 0; i < sz - 1; i++)
{
for (int j = 0; j < sz - i - 1; j++)
{
if (arr[j] > arr[j + 1])
{
int tmp;
tmp = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = tmp;
}
}
}
}
void arr_printf(int arr[], int sz)
{
for (int i = 0; i < sz; i++)
{
printf("%d ", arr[i]);
}
}
冒泡排序通过比较两个整数的大小,若前一个数比后一个数大,就交换这两个数,通过多次循环最后达到升序排列的效果。
但是冒泡排序具有局限性,他只能排列整型的顺序。
那如何实现对任意类型进行排序呢?
C语言提供了一个库函数qsort函数,它可以实现对任意类型进行排序。
2、qsort函数
void qsort (void* base, size_t num, size_t size,
int (*compar)(const void*,const void*));
我们来看一下他的四个参数,无返回值。
第一个参数是一个指针变量,它存放的的是数组首元素的地址。
第二个参数是数组中元素的个数。
第三个参数是每个元素的大小,单位是字节。
第四个参数是一个函数指针。指针指向一个函数,该函数用于比较两个元素的大小。
使用时需要自己定义一个比较函数。我们举个例子。
#include <stdio.h>
#include <stdlib.h> //使用qsort函数要包含头文件
int compar(const void* e1, const void* e2);
void arr_printf(int arr[], int sz);
int main()
{
int arr[10] = {10, 9, 8, 7, 6, 5, 4, 3, 2, 1};
qsort(arr, sizeof(arr) / sizeof(arr[0]), sizeof(arr[0]), compar);
arr_printf(arr, sizeof(arr) / sizeof(arr[0]));
return 0;
}
int compar(const void* e1, const void* e2)
{
return *(int*)e1 - *(int*)e2; //若前一个元素比后一个元素大,返回大于0的数
//若前一个元素比后一个元素小,返回小于0的数
//若前一个元素与后一个元素相等,则返回0
}
void arr_printf(int arr[], int sz)
{
for (int i = 0; i < sz; i++)
{
printf("%d ", arr[i]);
}
}
3、用冒泡函数模拟实现qsort函数
既然是模拟那函数也应该是这四个参数
void bubble_sort(void* base, int num, int size,
int (*compar)(const void*, const void*));
原冒泡排序程序:
for (int i = 0; i < sz - 1; i++)
{
for (int j = 0; j < sz - i - 1; j++)
{
if (arr[j] > arr[j + 1])
{
int tmp;
tmp = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = tmp;
}
}
}
用冒泡排序模拟,那冒泡函数的思想是不需要变的,只需要把if语句里的比较大小变成一个比较函数,为什么要变成函数呢?因为用户想进行排序的不一定是整形数组,还有可能是浮点型,短整型,结构体等多种数据类型(类似上一篇文章的回调函数思想),所以我们要调用一个函数,把不同数据类型数组中相邻元素的地址当参数传过来,若前一个元素比后一个元素大,返回大于0的数,若前一个元素比后一个元素小,返回小于0的数 ,若前一个元素与后一个元素相等,则返回0。代码如下
void bubble_sort(void* base, size_t num, size_t size,int (*compar)(const void*, const void*))
{
for (int i = 0; i < num - 1; i++)
{
for (int j = 0; j < num - i - 1; j++)
{
if (compare( (char*)base+size*j, (char*)base + size * (j+1) )> 0)
{
//交换数据
swap();
return
}
}
}
}
如果函数返回值大于0,则说明前一个元素比后一个元素大,我们想要得到升序的排列,那就应该交换,所以还应该写一个用于交换数据的函数。
void swap(char* a1 , char* a2, int size) //因为不知道具体类型,所以要一个字节一个字节的交换
{
for (int i = 0; i < size; i++)
{
char tmp;
tmp = *a1;
*a1 = *a2;
*a2 = tmp;
a1++;
a2++;
}
}
完整代码
#include <stdio.h>
void bubble_sort(void* base, size_t num, size_t size, int (*compar)(const void*, const void*));
void swap(char* a1, char* a2, int size);
int compare(const void* e1, const void* e2);
void arr_printf(int arr[], int sz);
int main()
{
int arr[] = { 10,9,8,7,6,5,4,3,2,1 };
int sz = sizeof(arr) / sizeof(arr[0]);
bubble_sort(arr, sizeof(arr)/sizeof(arr[0]), sizeof(int), compare);
arr_printf(arr, sz);
return 0;
}
void bubble_sort(void* base, int num, int size,int (*compar)( void*, void*))
{
for (int i = 0; i < num - 1; i++)
{
for (int j = 0; j < num - i - 1; j++)
{
if (compare( (char*)base+size*j, (char*)base + size * (j+1) )> 0)
{
//交换数据
swap((char*)base + size * j, (char*)base + size * (j + 1), size);
}
}
}
}
void swap(char* a1 , char* a2, int size)
{
for (int i = 0; i < size; i++)
{
char tmp;
tmp = *a1;
*a1 = *a2;
*a2 = tmp;
a1++;
a2++;
}
}
int compare(const void* e1, const void* e2)
{
return *(int*)e1 - *(int*)e2;
}
void arr_printf(int arr[], int sz)
{
for (int i = 0; i < sz; i++)
{
printf("%d ", arr[i]);
}
}
运行结果