目录
qsort函数
简介
- qsort函数是用来排序的
- 库函数,可以直接用来排序数据
- 底层使用的是快速排序的方式
排序算法:选择排序、冒泡排序、插入排序、快速排序、希尔排序
冒泡排序实现:
#include <stdio.h> int count = 0; void bubble_sort(int arr[], int sz) { int temp = 0; int i = 0; int j = 0; int flag = 1; for (i = 0; i < sz - 1; i++) { for (j = 0; j < sz - 1 - i; j++) { count++; if (arr[j] > arr[j + 1]) { temp = arr[j]; arr[j] = arr[j + 1]; arr[j + 1] = temp; flag = 0; } } if (flag == 1) { break; } } printf("%d\n", count); } void print(int arr[], int sz) { for (int i = 0; i < sz; i++) { printf("%d ", arr[i]); } printf("\n"); } int main() { int arr[10] = { 9,8,7,6,5,4,3,2,1,0 }; int sz = sizeof(arr) / sizeof(arr[0]); print(arr, sz); bubble_sort(arr, sz); print(arr, sz); return 0; }
- 从冒泡排序函数(bubble_sort)中可以看出,函数的形参只能是是整数
- 只能排序整形数据
qsort函数不同于上面的bubble_sort函数。qsort可以排序任意类型的数据
qsort概念
cplusplus中对qsort函数的定义
函数总共有四个参数:
- 第一个参数是一个指针,指向的是待排序的数组的第一个元素
- 第二个参数是base指向的待排序数组的元素个数
- 第三个参数是base所指向的待排序数组的元素的大小
- 第四个参数是一个函数指针,意味着使用qsort函数时要给第四个形参传递个函数指针过去
- 第四个参数是一个函数指针,qsort函数可以排序任意类型的数据,就比如要排序整形数据
- 对于上图方框中的代码,是用来比较两个整形数据的大小,但是两个字符串、两个结构体元素是不能使用><来进行比较的
- 在使用冒泡排序的情况,假设要改造这个函数,让他能够排序任意类型的数据
- 把两个元素比较的方法,封装成函数,把函数地址传给排序函数
- qsort函数参数的函数指针,指向的就是两个元素的比较函数
- qsort函数的返回值
- qsort函数有实现者
- qsort函数的使用者---要明确知道要排序的是什么数据,这些数据应该如何比较所以要提供两个元素的比较函数
- 所以qsort这个函数的第四个参数的函数指针,是要使用者自己编写,然后把函数地址传入到qsort函数的形参
qsort实践
排序整形数组
#include <stdio.h> #include <stdlib.h> void print(int arr[], int sz) { for (int i = 0; i < sz; i++) { printf("%d ", arr[i]); } printf("\n"); } //void *类型的指针,是无具体类型的指针,不能直接进行*操作,也不能进行+-整数的操作 //p1,p2为第一个要比较元素的地址和第二个要比较元素的地址 int cmp_int(const void* p1, const void* p2) { //如果p1所指向的元素大小<p2所指向的元素大小,返回<0的数字 //如果p1所指向的元素大小>p2所指向的元素大小,返回>0的数字 //如果p1所指向的元素大小=p2所指向的元素大小,返回=0 return *(int*)p1 - *(int*)p2; } int main() { int arr[] = { 9,8,7,6,5,4,3,2,1,0 }; int sz = sizeof(arr) / sizeof(arr[0]);//数组长度 qsort(arr, sz, sizeof(arr[0]), cmp_int); print(arr, sz); return 0; }
上述代码是升序排列,如果想降序:
int cmp_int(const void* p1, const void* p2) { //如果p1所指向的元素大小<p2所指向的元素大小,返回<0的数字 //如果p1所指向的元素大小>p2所指向的元素大小,返回>0的数字 //如果p1所指向的元素大小=p2所指向的元素大小,返回=0 return *(int*)p2 - *(int*)p1; }
直接修改return语句
排序结构体成员大小
#include <stdio.h> #include <stdlib.h> #include <string.h> struct Stu { char name[20]; int age; }; void print(struct Stu arr[], int sz) { for (int i = 0; i < sz; i++) { printf("%s %d\n", arr[i].name, arr[i].age); } } //比较两个结构体元素的大小 //可以选择使用名字或者年龄进行比较,选择其一 //按照年龄---整形比较 //按照名字---字符串比较 int cmp_stu_by_name(const void* p1, const void* p2)//通过名字进行比较 { return strcmp(((struct Stu*)p1)->name, ((struct Stu*)p2)->name); //strcmp按照对应字符的ASCII值进行比较 } int cmp_stu_by_age(const void* p1, const void* p2)//通过年龄进行比较 { return (((struct Stu*)p1)->age- ((struct Stu*)p2)->age); } int main() { struct Stu arr[3] = { {"zhangsan", 20},{"lisi", 35},{"wangwu",18} }; int sz = sizeof(arr) / sizeof(arr[0]);//数组长度 //qsort(arr, sz, sizeof(arr[0]), cmp_stu_by_name); qsort(arr, sz, sizeof(arr[0]), cmp_stu_by_age); print(arr, sz); return 0; }
qsort函数模拟实现
#include <stdio.h> #include <string.h> #include <stdlib.h> void Swap(char* buf1, char* buf2, size_t width) { for (int i = 0; i < width; i++) { char tmp = *buf1; *buf1 = *buf2; *buf2 = tmp; buf1++; buf2++; } } void bubble_sort(void* base, size_t sz, size_t width, int (*cmp)(const void* e1, const void* e2)) { //趟数 int i = 0; for (i = 0; i < sz; i++) { //每趟内部进行两两比较 for (int j = 0; j < sz - i - 1; j++) { //比较base[j]和base[j+1] //把base强转char *然后加上j*width就相当于base[j],不同的是此次可以比较任意类型 //base[j]和base[j+1]进行比较只能比较整形,或者说只能比较已知类型的base if (cmp((char*)base + width * j, (char*)base + width * (j + 1)) > 0)//改变 { //交换两个元素 //一大块数据分割成小块(char)进行交换 Swap((char*)base + width * j, (char*)base + width * (j + 1), width); } } } }
int compare_int(const void* e1, const void* e2) { return (*(int*)e1 - *(int*)e2); } void print(int arr[], int sz) { for (int i = 0; i < sz; i++) { printf("%d ", arr[i]); } printf("\n"); } //调用bubble_sort排序整形数组 void test1(void) { int arr[10] = { 9,1,8,7,6,4,5,3,2,0 }; int len = sizeof(arr) / sizeof(arr[0]); bubble_sort(arr, len, sizeof(arr[0]), compare_int); print(arr, len); } int main() { test1(); return 0; }
上述代码展示的是qsort模拟实现,对整型数组的元素进行了排序,当然也可以按照上面的qsort函数对任意类型的数据进行排序