这两个函数的头文件均为:#include<stdlib.h>
qsort是 quick sort 的简称,即快速排序,使用这个函数可以帮助我们按照我们想要的规则进行排序,比如字符排序,整形排序,浮点数排序以及数据体结构排序。
qsort()函数语法:void qsort ( void* base , size_t num , size_t size , int(*compare)(const void*,const void*) )
void* base:需要排序的数组,void* 表示任意的类型。
size_t :数组的另一种定义,size_t num:数组的大小。
size_t size:数组当中每一个元素的大小,常用sizeof(type)表示一种数据类型的大小。
int(*compare)(const void*,const void*) :表示自定义的一个排序函数。
//示例一,数组快速排序
//数组快速排序
#include<stdio.h>
#include<stdlib.h>
//compare 需要定义在主函数外面
int compare(const void* a,const void* b){
int* pa = (int*)a;
int* pb = (int*)b;
int num1 = *pa;//从指针获取值
int num2 = *pb;
return num1 - num2;//从小到大进行排序
}
void display(int arr[]){
int i;
for (i = 0;i < sizeof(arr);i++){
printf("%d\n",arr[i]);
}
}
int main(){
int arr[8] = {8,2,5,4,6,7,1,2};
qsort(arr,8,sizeof(int),compare);
display(arr);
}
一些解释:compare函数中的return值根据正负以及是否为0来排序,这个例子当中是从小到大进行排序,即num1-num2 > 0 则把num1放在num2后面的原理。
这里附上Python快速排序的写法:
#Python快速排序
def quickSort(arr):
if len(arr)<2:return arr
else:
mid = arr[len(arr)//2] #基准值,也可以选择第一个
left,right = [],[]
arr.remove(mid)
for num in arr:
if num >= mid:right.append(num)
else:left.append(num)
return quickSort(left)+[mid]+quickSort(right)
arr = [10,9,8,7,6,5,4,3,2,1]
print(quickSort(arr))
//示例二,浮点数排序
//浮点数进行快速排序
//从小到大
#include<stdio.h>
#include<stdlib.h>
int compare(const void* a,const void* b){
float* pa = (float*)a;
float* pb = (float*)b;
float num1 = *pa;
float num2 = *pb;
if (num1 - num2 > 0) return 1; //num1 - num2 > 0 ,就把大的数放在后边
else return -1; //注意不是返回 0
}
void display(int arr[]){
int i;
for (i = 0;i < sizeof(arr);i++){
printf("%f\n",arr[i]); //输出浮点数
}
}
int main(){
int arr[8] = {8.0,2.0,5.0,4.0,6.0,7.0,1.0,2.0};
qsort(arr,8,sizeof(float),compare);
display(arr);
}
一些解释:浮点数的比较,我们在写compare函数时依然是返回int 类型,是因为qsort()函数语法当中指定了传入的最后一个参数——函数int(*compare)(const void*,const void*) 返回类型必须是整型。所以我们根据num1 - num2 > 0返回正数(大于零的浮点数)写成返回值为1就可以解决这个问题了。其他的地方都要注意和之前的那些相比要改成float类型。
//示例三,数据体结构排序
这里我们假设创建了一个demo.txt的文本文档,里面存放着7位同学的姓名,语文成绩,数学成绩,英语成绩等信息,之后我们会这些读取信息然后存入我们创建的Student数据结构当中,之后根据语文成绩从大到小进行排序。
#include<stdio.h>
#include<stdlib.h>
typedef struct{ //创建数据结构Student
char name[30];
int chinese;
int math;
int english;
}Student;
Student students[7]; //实例化students数据结构对象
void readData(){
FILE* file = fopen("demo.txt","r"); //读取demo.txt当中的信息
int i;
for(i = 0;i<7;i++){
fscanf(file,"%s",students[i].name);
fscanf(file,"%d",&students[i].chinese);
fscanf(file,"%d",&students[i].math);
fscanf(file,"%d",&students[i].english);
}
fclose(file);
}
int compare(const void* a,const void* b){
Student* pa = (Student*)a;
Student* pb = (Student*)b;
int num1 = pa->chinese; //这里我们只关注语文成绩
int num2 = pb->chinese;
return num2 - num1; //从大到小进行排序
}
void display(){
int i;
for (i = 0;i < 7;i++){
printf("%s\t",students[i].name);
printf("%d\t",students[i].chinese);
printf("%d\t",students[i].math);
printf("%d\n",students[i].english);
}
}
int main(){
readData();
qsort(students,7,sizeof(Student),compare);
display();
}
如果我们想按照其他分数进行排序,只需要在compare 函数当中修改比较的值就可以了,比如我们想要按照数学成绩进行从大到小进行排序,compare 函数修改后代码如下:
//按照数学成绩从大到小排序
int compare(const void* a,const void* b){
Student* pa = (Student*)a;
Student* pb = (Student*)b;
int num1 = pa->math;
int num2 = pb->math;
return num2 - num1; //从大到小进行排序,即降序
}
以及如果我们想要按照总成绩进行降序排序,compare 函数修改如下:
//按照总成绩降序排序
int compare(const void* a,const void* b){
Student* pa = (Student*)a;
Student* pb = (Student*)b;
int num1 = pa->chinese + pa->math + pa->english;
int num2 = pb->chinese + pb->math + pb->english;
return num2 - num1;
}
接下来是bsearch() 函数。 bsearsh 是binary search 的简写,意思为二分搜索(查找)。用来查找一个元素是否在某个数组当中,查找的前提条件是给定数组一定是按照某个规则进行排列过的。bsearch()函数返回的是一个指针,所以不能直接输出,这点是需要注意的地方。
bsearch() 函数语法: void* bsearch( const void* key , const void* base , size_t num , size_t size , int (*compare)(const void* , const void* ))
const void* key : 需要查找的元素,这里需要注意的是我们传入的是该元素的指针
const void* base:查找的数组
size_t num: 数组的大小
size_t size: 数组当中每个元素的大小
int (*compare)(const void* , const void* ) : 定义比较规则的函数,这里的比较规则函数与qsort()定义的比较规则函数是不一样的。即compare 函数当中第一个参数表示需要查找的元素,第二个参数表示数组当中的每一个元素。
//示例四,查找语文成绩为100 的同学
#include<stdio.h>
#include<stdlib.h>
typedef struct{
char name[30];
int chinese;
int math;
int english;
}Student;
Student students[7];
void readData(){
FILE* file = fopen("demo.txt","r");
int i;
for(i = 0;i<7;i++){
fscanf(file,"%s",students[i].name);
fscanf(file,"%d",&students[i].chinese);
fscanf(file,"%d",&students[i].math);
fscanf(file,"%d",&students[i].english);
}
fclose(file);
}
int compare1(const void* a,const void* b){
Student* pa = (Student*)a;
Student* pb = (Student*)b;
int num1 = pa->chinese;
int num2 = pb->chinese;
return num2 - num1;
}
int compare2(const void* key,const void* e){
int* pNum1 = (int*)key; //获取需要查找的元素key 的指针
Student* pS = (Student*)e; //获取查找数组当中元素e 的指针
int num1 = *pNum1; //获取key 的值
int num2 = pS->chinese; //获取e 的值
return num2 - num1; //返回的是比较规则,从大到小进行排序
}
int main(){
readData();
qsort(students,7,sizeof(Student),compare1);//第一个比较函数
int key = 100;
//接收bsearch() 函数返回的指针
Student* s = bsearch(&key,students,7,sizeof(Student),compare2);//第二个比较函数
printf("%s\n",s->name);
}