1.了解qsort
qsort函数是C语言中的一个标准库函数,它的头文件#include<stdlib.h>,用来对于数组内的元素进行快速排列。它可以对任意数据类型进行排列,但前提是要提供相应的比较函数即可。qsort原形是:
void qsort(void *base,size_t nitems,size_t size,int (*compar)(const void*,const void*))
1.base用来指向数组的指针,因为我们不知道比较的数据类型,所以用通用的数据类型void*来接收,base接收数组首元素地址,得到数组首元素地址后,便可以得到后面一系列的元素,来进行比较。
2.nitems是数组中的元素个数,元素不能是负数,所以用size_t(无符合整数类型)来接收。
3.size是指数组中每个元素的内存大小,也不能为负,用size_t接收。
4.compar是函数指针,用来指向一个比较函数,因为不同的数据类型比较方式不一样,比较函数也不一样,这是需要我们自己根据比较的数据,自行提供对应的比较函数。
比较函数需要返回一个整数值,当两个元素相等时返回0,当第一个元素小于第二个元素,返回负数,当第一个元素大于第二个元素,返回正数。
2.qosrt使用:
2.1用qsort排序整形:
#include<stdio.h> #include<stdlib.h> int com(const void* p1, const void* p2) { return *(int*)p1 - *(int*)p2; } int main() { int num=0, sz=0,i=0;//num数组元素个数,sz每个元素内存大小 int arr[10] = { 1,9,2,8,3,7,4,6,5,10 }; num = sizeof(arr) / sizeof(arr[0]); sz = sizeof(arr[0]); qsort(arr, num, sz, com); for ( i = 0; i < num; i++) { printf("%d ", arr[i]); } }
代码运行结果:
1.在com函数中,每次接收两个元素进比较,比较完后,又接收后面的元素,两两进行比较,直到比较完为止。(这些都是在qsort函数内部实现的)
2.在com函数中,返回值若为正数(前一个元素大于后一个元素),前一个元素和后一个元素就交换,最后的到的就是升序的数组。这是qsort函数内部实现的。
3.因为我们知道要比较的是两个整形,所以在com函数中,我们强制转换为int*,根据比较数据类型进行强制转换的。
2.2用qsort排序结构数据结构:
定义一个结构体:
struct student { char name[20];//名字 int age;//年龄 };
我们可以排序名字和年龄,排列名字时(字符串),需要用到strcmp(比较字符串),它头文件#include<string.h>,基本形式strcmp(str1,str2),如果str1==str2则返回0,str1>str2则返回正数,str1<str2则返回负数。
2.2.1用代码实现用qsort排序名字:
#include<stdio.h> #include<stdlib.h> #include<string.h> struct student { char name[20]; int age; }; int com_name(const void* p1, const void* p2) { return strcmp(((struct student*)p1)->name, ((struct student*)p2)->name); } int main() { int num=0, sz=0,i=0; struct student arr[3] = { {"zhangsan",22},{"lisi",30},{"wangwu",19}}; num = sizeof(arr) / sizeof(arr[0]); sz = sizeof(arr[0]); qsort(arr, num, sz, com_name); for ( i = 0; i < num; i++) { printf("%s %d\n", arr[i].name,arr[i].age); } }
运行结果:
2.2.2用代码实现用qsort排序年龄:
只需要修改比较函数内部就完成了。
#include<stdio.h> #include<stdlib.h> #include<string.h> struct student { char name[20]; int age; }; int com_age(const void* p1, const void* p2) { return ((struct student*)p1)->age - ((struct student*)p2)->age; } int main() { int num=0, sz=0,i=0; struct student arr[3] = { {"zhangsan",22},{"lisi",30},{"wangwu",19}}; num = sizeof(arr) / sizeof(arr[0]); sz = sizeof(arr[0]); qsort(arr, num, sz, com_age); for ( i = 0; i < num; i++) { printf("%s %d\n", arr[i].name,arr[i].age); } }
运行结果:
3.qsort函数模拟实现:
3.1分布实现模拟qsort函数:
首先,我们要知道在qsort中进行了元素比较和元素交换的操作。
首先从最简单的比较整数:
我们要定义一个比较两个元素大小的函数和一个交换两个元素的函数。
比较函数:
不同的数据类型进比较,强制转化类型不一样。整形数据比较,就强转为整形比较。
int compare(void *p1,void *p2) { return *(int*)p1-*(int*)p2; }
交换函数:因为我们每次比较的数据类型不一样,比如,整形交换是一次性交换四个字节,而字符比较交换一个字节,不同的结构体数据类型大小都不一样,交换的大小都不一样。为了方便起见,我们交换时,采用一个字节一个字节交换,比如交换整形时,我们交换四次,就是四个字节。
void swap(char*p1,char*p2,size_t size) { int i=0; char temp; for(i=0;i<size;i++) { temp=*p1; *p1=*p2; *p2=temp; p1++; p2++; } }
我们再用copy_qsor函数t模拟qsort函数。
我们采用冒泡排序的思想:
void copy_qsort (void *base,size_t number,size_t size,int(*cmp)(void *p1,void *p2)) { int i=0,j=0; for(i=1;i<number;i++) { for(j=0;j<=number-1-i;j++) { if(compare((char*)base+j*size,(char*)base+(j+1)*size)>0) { swap((char*)base+j*size,(char*)base+(j+1)*size,size); } } } }
3.2用模拟qsort函数进行整形数据排序:
实践代码:
#include<stdio.h> #include<stdlib.h> #include<string.h> int compare(void* p1, void* p2) { return *(int*)p1 - *(int*)p2; } void swap(char* p1, char* p2, size_t size) { int i = 0; char temp; for (i = 0; i < size; i++) { temp = *p1; *p1 = *p2; *p2 = temp; p1++; p2++; } } void copy_qsort(void* base, size_t number, size_t size, int(*cmp)(void* p1, void* p2)) { int i = 0, j = 0; for (i = 1; i < number; i++) { for (j = 0; j <= number - 1 - i; j++) { if (compare((char*)base + j * size, (char*)base + (j + 1) * size) > 0) { swap((char*)base + j * size, (char*)base + (j + 1) * size, size); } } } } int main() { int num = 0, sz = 0, i = 0; int arr[10] = { 1,9,2,8,3,7,6,4,10,5 }; num = sizeof(arr) / sizeof(arr[0]); sz = sizeof(arr[0]); copy_qsort(arr, num, sz, compare); for (i = 0; i < num; i++) { printf("%d ", arr[i]); } return 0; }
运行结果
3.3用模拟qsort进行结构体排序:
这里我就只排序名字,年龄排序如2.2.2
#include<stdio.h> #include<stdlib.h> #include<string.h> struct student { char name[20]; int age; }; int compare(void* p1, void* p2) { return strcmp(((struct student*)p1)->name, ((struct student*)p2)->name); } void swap(char* p1, char* p2, size_t size) { int i = 0; char temp; for (i = 0; i < size; i++) { temp = *p1; *p1 = *p2; *p2 = temp; p1++; p2++; } } void copy_qsort(void* base, size_t number, size_t size, int(*cmp)(void* p1, void* p2)) { int i = 0, j = 0; for (i = 1; i < number; i++) { for (j = 0; j <= number - 1 - i; j++) { if (compare((char*)base + j * size, (char*)base + (j + 1) * size) > 0) { swap((char*)base + j * size, (char*)base + (j + 1) * size, size); } } } } int main() { int num = 0, sz = 0, i = 0; struct student arr[3] = { {"zhangsan",19},{"lisi",28},{"wangwu",23}}; num = sizeof(arr) / sizeof(arr[0]); sz = sizeof(arr[0]); copy_qsort(arr, num, sz, compare); for (i = 0; i < num; i++) { printf("%s %d\n", arr[i].name,arr[i].age); } return 0; }
运行结果:
希望我写的能给大家带来帮助,如有错误希望大家指出,谢谢大家支持。