模拟实现库函数qsort - 冒泡排序 - C语言

模拟实现库函数qsort - 冒泡排序 - C语言

库函数qsort的简单介绍

函数功能

库函数qsort(quick sort)基于八大排序算法中的快速排序,能够排序任意数据类型的数组其中包括整型,浮点型,字符串甚至还有自定义的结构体类型。
qsort1

函数返回类型及函数参数

qsort2

返回类型:void - 无返回值。
函数参数:

  • void* base - 待排序数据的的起始地址。
  • size_t num - 待排序数据中的元素个数。
  • size_t width - 数据元素占内存空间大小,单位是字节。
  • int (__cdecl *compare )(const void *elem1, const void *elem2 ) - 函数指针,指向一个比较两个元素大小的函数compare。
比较函数compare

比较函数需要用户自定义。
比较函数使得qsort通用性更好,有了比较函数,qsort可以实现对整型、浮点型、字符串、结构体等任意类型进行升序或降序排序。
int compare(const void* elem1, const void* elem2)
返回类型:int 类型
qsort3

函数参数:const void* elem1, const void* elem2 - 两个const修饰的无类型指针,用来接收待比较的两个元素。

头文件

头文件:<stdlib.h>

模拟实现qsort - bubble_sort

在对库函数qsort有了一些了解之后,我们就要开始尝试用冒泡排序算法模拟实现qsort,即bubble_sort。

函数bubble_sort

函数swap用以交换两个元素,放在bubble_sort函数之前,方便bubble_sort函数调用。

void swap(char* buf1, char* buf2, size_t width)//交换两个元素
{
       //参数:1.两个待交换元素的首地址 2.元素占内存空间大小,单位是字节
       //基本算法:交换每个字节的数据
       unsigned int i = 0;
       for (i = 0; i < width; i++)
       {
              char temp = *buf1;//中间变量
              *buf1 = *buf2;
              *buf2 = temp;
              buf1++;
              buf2++;
       }
}
void bubble_sort(void* base, size_t num, size_t width, int (*cmp)(const void* elem1, 
const void* elem2))//冒泡排序模拟实现库函数qsort
{
       unsigned int i = 0;//趟数
       for (i = 0; i < num - 1; i++)
       {
              //排序一趟
              unsigned int j = 0;
              for (j = 0; j < num - 1 - i; j++)
              {
                      //调用比较函数
                      if (cmp((char*)base + j * width, (char*)base + (j + 1) * width) 
> 0)
                      {
                             //交换两个元素
                             swap((char*)base + j * width, (char*)base + (j + 1) * 
width, width);
                      }
              }
       }
}

以上就是函数bubble_sort的全部代码,我们知道,该函数可以排序任意类型,所以我们搭建了几种函数环境用以测试函数bubble_sort的运行情况。

测试函数运行情况

整型test_int
int cmp_int(const void* elem1, const void* elem2)//比较整型元素大小
{
       return *(int*)elem1 - *(int*)elem2;//返回两个元素的差
}
void print_int(int arr[], unsigned int sz)//打印整型数组
{
       unsigned int i = 0;
       for (i = 0; i < sz; i++)//遍历数组
       {
              printf("%d ", arr[i]);
       }
       printf("\n");
}
void test_int()//整型测试环境
{
       int arr[] = { 1,3,5,7,9,2,4,6,8,0 };
       unsigned int sz = sizeof(arr) / sizeof(arr[0]);
       print_int(arr, sz);//排序前打印
       bubble_sort(arr, sz, sizeof(arr[0]), cmp_int);//调用函数排序
       print_int(arr, sz);//排序后打印
}

运行结果:
qsort4

浮点型test_doubble
int cmp_double(const void* elem1, const void* elem2)//比较两个浮点型大小
{
       return (int)(*(double*)elem1 - *(double*)elem2);//返回两个元素的差值
}
void print_double(double arr[], unsigned int sz)//打印浮点型数组
{
       unsigned int i = 0;
       for (i = 0; i < sz; i++)
       {
              printf("%.2lf ", arr[i]);
       }
       printf("\n");
}
void test_double()//整型测试环境
{
       double arr[] = { 1.0,3.0,5.0,7.0,9.0,2.0,4.0,6.0,8.0,0.0 };
       unsigned int sz = sizeof(arr) / sizeof(arr[0]);
       print_double(arr, sz);//排序前打印
       bubble_sort(arr, sz, sizeof(arr[0]), cmp_double);//调用函数排序
       print_double(arr, sz);//排序后打印
}

运行结果:
qsort5

字符型test_char
int cmp_char(const void* elem1, const void* elem2)//比较字符大小
{
       return *(char*)elem1 - *(char*)elem2;
}
void print_char(char ch[], unsigned int sz)//打印字符型数组
{
       unsigned int i = 0;
       for (i = 0; i < sz; i++)
       {
              printf("%c ", ch[i]);
       }
       printf("\n");
}
void test_char()//字符型测试环境
{
       char ch[] = { 'd','e','a','k','h','g','t','b' };
       unsigned int sz = sizeof(ch) / sizeof(ch[0]);
       print_char(ch, sz);//排序前打印
       bubble_sort(ch, sz, sizeof(ch[0]), cmp_char);//调用函数
       print_char(ch, sz);//排序后打印
}

运行结果:
qsort6

结构体类型test_struct

结构体类型排序需要指定一个排序标准。

int cmp_struct_name_strlen(const void* elem1, const void* elem2)//比较名字长度大小
{
       return (strlen(((struct Stu*)elem1)->name) - strlen(((struct 
Stu*)elem2)->name));
}
int cmp_struct_name_strcmp(const void* elem1, const void* elem2)//比较名字首字母大小
{
       return strcmp(((struct Stu*)elem1)->name, ((struct Stu*)elem2)->name);
}
int cmp_struct_age(const void* elem1, const void* elem2)//比较年龄大小
{
       return (*(int*)elem1 - *(int*)elem2);
}
void print_struct(struct Stu stu[], unsigned int sz)//打印结构体类型数组
{
       unsigned int i = 0;
       for (i = 0; i < sz; i++)
       {
              printf("%s %d ", stu[i].name, stu[i].age);
       }
       printf("\n");
}
void test_struct()//结构体类型测试环境
{
       struct Stu stu[] = { {"zhangsan",38},{"qiansi",45},{"wangwu",30} };
       unsigned int sz = sizeof(stu) / sizeof(stu[0]);
       print_struct(stu, sz);//排序前打印
       bubble_sort(stu, sz, sizeof(stu[0]), cmp_struct_name_strlen);//根据名字长度排序
       print_struct(stu, sz);//名字长度排序后打印
       //bubble_sort(stu, sz, sizeof(stu[0]), cmp_struct_name_strcmp);//根据名字首字母排序
       //print_struct(stu, sz);//名字首字母排序后打印
       //bubble_sort(stu, sz, sizeof(stu[0]), cmp_struct_age);//根据年龄排序
       //print_struct(stu, sz);//年龄排序后打印
}

运行结果:
根据名字长度排序:
qsort7

根据名字首字母排序:
qsort8

根据年龄排序:
qsort9

以上就是我们对几种不同类型的数组进行的排序测试,从运行结果可见函数实现的很成功。
注:本次测试均采用升序测试,若需降序,只需将比较函数中return语句内的两个变量交换位置即可。
总而言之,qsort函数实现对不同元素的排序主要就是通过对compare函数进行定义实现的,我们的bubble_sort函数也是如此,对于每一种变量类型的排序,我们都需要重新实现一种compare函数。但即便如此,qsort函数也极大地方便了程序员们。
到这里,我们对库函数qsort的模拟就结束了,你学会了吗!

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值