C语言中的qsort函数(详解)

m0_61315608 2024-08-07 15:05:02 阅读 83

目录

一、qsort 函数的简介

二、qsort 函数的含义

2.1 函数原型及参数解释

2.2比较函数函数原型 

三、通过不同类型数据测试 qsort 函数排序 

3.1对整型数组进行排序

3.2对浮点型数组进行排序

3.3对结构体类型数据进行排序

四、冒泡排序模拟实现qsort函数


一、qsort 函数的简介

        在C语言中对数据的排序方式有很多种:选择排序、冒泡排序、归并排序、快速排序。我们从名字去理解就知道快速排序是目前公认的比较好的一种排序算法。快速排序从名字就可以知道它的排序速度很快,为什么会比其他排序方式快呢?因为它在C语言库中已经实现了,我们在排序的时候只需要去调用它就行,这就是 qsort 函数(全称 quick sort),其声明在 stdlib.h 头文件中,它可以按照指定的比较函数对任意数据类型的数组进行排序,包括整型、浮点型、字符型甚至自定义的结构体类型。

二、qsort 函数的含义

        通过网站cplusplus.com - The C++ Resources Network或 msdn 程序搜索 qsort 函数。

翻译为:

2.1 函数原型及参数解释

qsort 函数原型及参数解释

void qsort (

     void* base,         //指向要排序的数组的首元素的指针

     size_t num,         //待排序数组中元素的个数

     size_t size,        //待排序数组中每个元素的大小(以字节为单位)

int (*compar)(const void*,const void*) //比较函数的指针,用于确定元素之间的排序

);

2.2比较函数函数原型 

比较函数的原型如下:

<code>int compar(const void *a, const void *b);

比较函数需要返回一个整数值,表示两个元素之间的关系:

如果返回值小于0,则表示a应该排在b之前。如果返回值等于0,则表示a和b相等,它们的相对顺序不变。如果返回值大于0,则表示a应该排在b之后。

注意: 使用qsort函数时,需要根据实际情况编写一个合适的比较函数来确定排序规则。比较函数可以根据元素的类型和排序需求进行自定义。

三、通过不同类型数据测试 qsort 函数排序 

3.1对整型数组进行排序

#include <stdio.h>

#include <stdlib.h>

int cmp_int(const void* p1, const void* p2)

{

return *((int*)p1) - *((int*)p2);

}

int main()

{

int arr[] = { 1,9,2,8,3,7,4,6,5,0 };

qsort(arr, sizeof arr / sizeof arr[0], sizeof(int), cmp_int);

int i = 0;

for (i = 0; i < sizeof arr / sizeof arr[0]; i++)

{

printf("%d ", arr[i]);

}

return 0;

}

运行结果

         由此,我们就完成调用 qsort 函数实现整型数组的升序排序。如果我们要实现降序排序呢,怎么实现?

        我们只需要将 p1 与 p2 调换一下位置就可以实现降序排序。在上面我们介绍过了比较函数需要返回一个整数值,我们就是通过返回的这个值确定如何去排序的。当返回值小于0时, p1 就排在 p2 的前面;等于0时相对位置不变;大于0时,p1 排在 p2 后面。

3.2对浮点型数组进行排序

<code>#include <stdio.h>

#include <stdlib.h>

int cmp_float(const void* p1, const void* p2)

{

return *((float*)p1) - *((float*)p2);

}

int main()

{

float arr[] = { 1.3, 9.5, 2.8, 8.9, 3.6, 7.2, 4.7, 6.9, 5.5, 0.22 };

qsort(arr, sizeof(arr) / sizeof(arr[0]), sizeof(float), cmp_float);

int i = 0;

for (i = 0; i < sizeof(arr) / sizeof(arr[0]); i++)

{

printf("%.2f ", arr[i]);

}

return 0;

}

运行结果

3.3对结构体类型数据进行排序

        在我们学习结构体数据排序前我们需要清楚两个结构体类型的数据是不能直接使用 > 、< 、== 进行比较的。

<code>#include <stdio.h>

#include <stdlib.h>

#include <string.h>

struct stu

{

char name[20];//姓名

int age;//年龄

};

int cmp_struct_char(const void* p1, const void* p2)

{

//两个字符串同样也是不能使用 > < ==进行比较的

//在C语言中使用库函数strcmp进行两个字符串的比较

//比较的是对应位置的ASCII码值的大小,同时需要引用头文件<string.h>

return strcmp(((struct stu*)p1)->name, ((struct stu*)p2)->name);

}

int main()

{

struct stu s[] =

{

{"zhangsan" , 32},

{"lisi", 18},

{"xiaoming", 34}

};

//对结构体类型中的字符串进行排序

qsort(s, sizeof(s) / sizeof(s[0]), sizeof(s[0]), cmp_struct_char);

return 0;

}

我们通过调试去观察排序效果

注意:结构体指针访问它所指向对象的成员时 “->” 不需要 进行解引用(仅限结构体指针)。

四、冒泡排序模拟实现qsort函数

<code>#include <stdio.h>

#include <string.h>

void Swap(char* p1, char* p2, size_t size)

{

int i = 0;

for (i = 0; i < size; i++)

{

char tmp = *(p1 + i);

*(p1 + i) = *(p2 + i);

*(p2 + i) = tmp;

}

}

void bubble_sort(void* base, size_t sz, size_t width, int (*cmp)(const void* p1,const void* p2))

{

int i = 0;

//趟数

for (i = 0; i < sz - 1; i++)

{

//每一趟冒泡排序的过程

int j = 0;

for (j = 0; j < sz - 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);

}

}

}

}

struct stu {

char name[20];

int age;

};

int cmp_struct_by_name(const void* p1, const void* p2)

{

return strcmp(((struct stu*)p1)->name, ((struct stu*)p2)->name);

}

int cmp_struct_by_age(const void* p1, const void* p2)

{

return ((struct stu*)p1)->age - ((struct stu*)p2)->age;

}

void test1()

{

struct stu arr[] =

{

{"zhangsan" , 32},

{"lisi", 18},

{"xiaoming", 34}

};

bubble_sort(arr, sizeof(arr) / sizeof(arr[0]), sizeof(arr[0]), cmp_struct_by_name);

//bubble_sort(arr, sizeof(arr) / sizeof(arr[0]), sizeof(arr[0]), cmp_struct_by_age);

int i = 0;

for (i = 0; i < sizeof(arr) / sizeof(arr[0]); i++)

{

printf("%s %d\n", arr[i].name, arr[i].age);

}

}

int main()

{

test1();

return 0;

}

总体实现:



声明

本文内容仅代表作者观点,或转载于其他网站,本站不以此文作为商业用途
如有涉及侵权,请联系本站进行删除
转载本站原创文章,请注明来源及作者。