白色的风车,安静的转着..........................................................................................................
前言
介绍了qsort函数,以及对冒泡排序进行了升级。
一、【qsort函数的介绍及使用】
1.1【qsort函数的介绍】
首先qsort函数是一个库函数,是用来排序的库函数,底层采用快速排序的思想。而且它可以排序任何类型的数据
返回值:
注意:
1. int(*cmpare)(const void* e1, const void* e2)
它的返回类型固定为int。
其中cmp是函数指针,cmpare指向的是:排序时,用来比较两个元素的函数。需要使用函数的人自己编写。
1.2【qsort函数的使用】
在讲解如何使用之前,先来看一下函数参数中出现的指针——void *
他表示的是无具体类型的指针,因此她能够接受任意类型的地址,这也是qsort可以排序任何类型的数据的原因。而它的缺点是,不能进行运算,也不能进行解引用
qsort是可以排序任何类型的数据:
1.比较两个整数,用 >,<,==
#include <stdio.h> #include <stdlib.h> #include <string.h> //使用者提供的比较函数。 int cmp_int(const void* p1, const void* p2) { return *(int*)p1 - *(int*)p2; } void print(int arr[], int sz) { for (int i = 0; i < sz; i++) { printf("%d ", arr[i]); } } //测试使用qsort排序整形数据 void test1() { int arr1[] = { 9,8,7,6,5,4,3,2,1,0 }; int sz = sizeof(arr1) / sizeof(arr1[0]); //使用qsort来排序整型数组。需要提供一个能够比较两个整数大小的函数。 qsort(arr1, sz, sizeof(arr1[0]),cmp_int); //使用打印函数,打印数组。 print(arr1, sz); } int main() { test1(); //test2(); return 0; }
2.比较浮点数:
void print(float arr[], int sz) { for (int i = 0; i < sz; i++) { printf("%f ", arr[i]); } } int cmp_float(const void* p1, const void* p2) { //不这样写:return (*(float*)p1) - (*(float*)p2);的原因是: //强转为int类型后,可能有误差,0.2-0.1=0.1(int)强转后变为0; //这是由于强转为int类型,只会保留整数部分,舍去小数部分 //return (int)(*(float*)p1) - (int)(*(float* )p2); if ((*(float*)p1) - (*(float*)p2) > 0.0000) { return 1; } else if ((*(float*)p1) - (*(float*)p2) == 0.0000) { return 0; } else { return -1; } } void test2() { float brr[] = { 0.2f,0.1f,9.4f,1.8f,0.2f }; int sz = sizeof(brr) / sizeof(brr[0]); qsort(brr, sz, sizeof(brr[0]), cmp_float); print(brr, sz); } int main() { //使用qsort操作整形。 //test1(); //使用qsort操作浮点数。 test2(); //使用qsort操作字符类型 //test3(); //使用qsort函数操作结构体。 //test4(); }
运行结果:
3.比较字符,注意强制类型转换为int,因为本质是比较ASCII值
int cmp_char(const void* p1, const void* p2) { return *(char*)p1 - *(char*)p2; } void print(char arr[], int len) { for (int i = 0; i < len; i++) { printf("%c ", arr[i]); } } void test3() { //1.字符数组的形式 //char crr[] = { 'c' ,'b','d','s','l'}; //2.字符串的形式 char crr[] = "gcbdfe"; int len = sizeof(crr)/sizeof(crr[0]);//注意sizeof和strlen的区别 qsort(crr, len-1, sizeof(crr[0]), cmp_char);//sizeof计算的有\0的长度,所以需要-1。 print(crr,len-1); } int main() { //使用qsort操作整形。 //test1(); //使用qsort操作浮点数。 //test2(); //使用qsort操作字符类型 test3(); //使用qsort函数操作结构体。 //test4(); }
运行结果:
4.比较结构体如(学生:张三,20岁)指定比较标准,即用年龄还是名字来进行比较。
#include <stdio.h> #include <string.h> #include <stdlib.h> //测试使用qsort排序结构体数据 struct Stu { char name[20]; int age; }; //按照年龄来排的函数 int cmp_stu_byage(const void* p1, const void* p2) { return ((struct Stu*)p1)->age - ((struct Stu*)p2)->age; } //按照名字来排序的函数 int cmp_stu_byname(const void* p1, const void* p2) { return strcmp(((struct Stu*)p1)->name, ((struct Stu*)p2)->name); } void test2() { struct Stu s[] = { {"zhangsan",20},{"lisi",25},{"wangwu",50} }; //按照年龄来排 int sz = sizeof(s) / sizeof(s[0]); /*qsort(s, sz, sizeof(s[0]), cmp_stu_byage); printf("%s %d\n", s[0].name,s[0].age); printf("%s %d\n", s[0].name,s[1].age); printf("%s %d\n", s[0].name,s[2].age);*/ //按照名字来排序 qsort(s, sz, sizeof(s[0]), cmp_stu_byname); qsort(s, sz, sizeof(s[0]), cmp_stu_byage); printf("%s %d\n", s[0].name, s[0].age); printf("%s %d\n", s[1].name, s[1].age); printf("%s %d\n", s[2].name, s[2].age); //按照名字来排序 } int main() { //test1(); test2(); return 0; }
二、【冒泡排序升级】
在【冒泡排序】中已经简单的了解了冒泡排序的思想,但是当时,只能对整形进行排序,今天对他进行升级。不理解的要去【冒泡排序】适当复习一下哦。
话不多说,先给代码:
//bubble_sort升级 int cmp_int(const void* p1, const void* p2)//使用者提供的比较函数。 { return *(int*)p1 - *(int*)p2; } void print(int arr[], int sz)//打印排序后的数组 { for (int i = 0; i < sz; i++) { printf("%d ", arr[i]); } } void Swap(char* s1, char* s2,int size)//有画图的分析,分析编写思路及原因 { for (size_t i = 0; i < size; i++) { char tmp = *s1; *s1 = *s2; *s2 = tmp; s1++; s2++; } } void bubble_sort(void* base, size_t num, size_t size, int(*cmp)(const void* e1, const void* e2)) { //确定冒泡排序的趟数 for (size_t i = 0; i < num - 1; i++) { int flag = 1;//优化代码,假设每趟冒泡排序都已经排序完成,那么就不需要再进行交换了。 //每趟的比较 for (size_t j = 0; j < num - 1 - i; j++) { if (cmp((char *)base+j*size,(char *)base+(j+1)*size) > 0)//有画图的分析 { flag = 0;//只要需要交换,说明没有排序完成,把flag置成0 //交换 Swap((char*)base + j * size, (char*)base + (j + 1) * size,size);//不满足 //条件进则行交换 } } if (flag == 1)//如果flag==1,说明已经排序完成,则跳出循环。 { break; } } } void test() { int arr[]={ 3,6,4,2,1,9,18 };//定义测试用例 int sz = sizeof(arr) / sizeof(arr[0]); bubble_sort(arr, sz, sizeof(arr[0]), cmp_int); print(arr, sz); } int main() { test();//编写测试代码 return 0; }
运行结果:
画图分析:
总结
本章完,感谢观看。
谢谢你让我听见,因为我在等待永远........................................................................................
————《白色风车》