目录
?C 库函数-?qsort()概念
?一个冒泡排序
? ? ? ? ??利用qsort解决
? ? ? ? ? ·void*?指针
???????????·qsort 实现
利用qsort结构体排序
???·?名字的排序
???·年龄的排序
?模拟实现qsort
?模拟qsort对数组的排序
????????解析
?·主函数
??·比较函数
??·交换函数
??·基于冒泡排序的思想实现qsort的函数
?排序结构体数据
??·结果
??结束语
C 库函数<stdlib.h>-?qsort()概念
qsort - 这个函数可以判刑任意类型的数据
为了防止歧义,这里引用了官方解释,下面我会详解
void qsort (void* base, size_t num, size_t size,
int (*compar)(const void*,const void*));
1.void* base //要排序的数据的起始位置
2.size_t num //待排序的数据元素的个数
3.size_t size? //待排序的数据元素的大小(单位是字节)
4.int (*compar)(const void*,const void*) //函数指针-一个比较函数
一个冒泡排序
//一个冒泡排序
void bubble_sort(int *arr, int sz)
{
int i = 0;
//趟数
for ( i = 0; i < sz-1; i++)
{
int flag = 1;
//交换
int j = 0;
for ( j = 0; j < sz-1-i; j++)
{
if (*(arr+j)>*(arr+j+1))
{
int tmp = *(arr + j);
*(arr + j) = *(arr + j + 1);
*(arr + j + 1) = tmp;
flag = 0;
}
}
if (flag)
{
break;
}
}
}
int main() {
int arr[] = { 9,8,7,6,5,4,3,2,1,0 };
//升序排序
int sz = sizeof(arr) / sizeof(arr[0]);
bubble_sort(arr, sz);
int i = 0;
for ( i = 0; i < sz; i++)
{
printf("%d ",arr[i]);
}
return 0;
}
利用qsort解决
void*?指针
在开始代码的时候我们先要了解?void*?指针的类型
//void* 的作用
int main()
{
int a = 10;
char* pa = &a; //warning C4133: “初始化”: 从“int *”到“char *”的类型不兼容
//类型不兼容是会报警告的
//void* pv = &a; //这样子就不会有问题了
}
通常我们使用指针的时候都是一一对应,什么类型的数据地址就应该用什么类型的指针来接收,但有的情况下我们并不知道我们所接收的数据的类型是什么,因此便有了?void*?指针,这个类型的指针可以接收任意类型数据的地址,以来存储使用
?qsort 实现
?--使用的时候记得引入头文件 <stdlib.h>
?#include<stdlib.h>
#include<stdio.h>
int cmp_int(const void*e1, const void*e2)
{
return ( *(int*)e1 - *(int*)e2 ); //直接返回数据就行了
//这是升序排序,当我们想要降序判刑只要交换e1、e2的位置就行了,逻辑交换的道理
}
int main() {
int arr[] = { 9,8,7,6,5,4,3,2,1,0 };
//升序排序
int sz = sizeof(arr) / sizeof(arr[0]);
//bubble_sort(arr, sz);
qsort(arr, sz, sizeof(arr[0]), cmp_int);
int i = 0;
for ( i = 0; i < sz; i++)
{
printf("%d ",arr[i]);
}
return 0;
}
?
//需要注意的是传过去的函数的规定 int compareMyType(const void* a, const void* b) { ?? ??? ?if (*(MyType*)a < *(MyType*)b) return -1;?? ?//返回一个小于0的数 ?? ??? ?if (*(MyType*)a == *(MyType*)b) return 0;?? //返回0 ?? ??? ?if (*(MyType*)a > *(MyType*)b) return 1;?? ?//返回一个大于0的数 }
//还要注意的是要强制类型
结果和冒泡排序的效果是一样的?
利用qsort结构体排序
?名字的排序
#include<stdlib.h>
#include<stdio.h>
#include<string.h>
struct Stu
{
char name[20];
int age;
};
cmp_stu_by_name(const void* e1, const void* e2)
{
return strcmp(((struct Stu*)e1)->name, ((struct Stu*)e2)->name);
//同样的需要强制转化类型成我们创立的结构体类型 (struct Stu*)
}
void test()
{
//qsort来排序结构体数据
struct Stu s[] = {{"zhangsan",15}, {"lisi",30}, {"wangwu",25}}; //创立一个结构体数据
int sz = sizeof(s) / sizeof(s[0]);
qsort(s, sz, sizeof(s[0]), cmp_stu_by_name);
}
int main() {
test();
return 0;
}
?
年龄的排序
#include<stdlib.h>
#include<stdio.h>
#include<string.h>
struct Stu
{
char name[20];
int age;
};
//按名字字母排序
cmp_stu_by_name(const void* e1, const void* e2)
{
return strcmp(((struct Stu*)e1)->name, ((struct Stu*)e2)->name);
}
//按年龄的升序排序
cmp_stu_by_age(const void* e1, const void* e2)
{
return ((struct Stu*)e1)->age - ((struct Stu*)e2)->age;
}
void test()
{
//qsort来排序结构体数据
struct Stu s[] = {{"zhangsan",15}, {"lisi",30}, {"wangwu",25}};
int sz = sizeof(s) / sizeof(s[0]);
//qsort(s, sz, sizeof(s[0]), cmp_stu_by_name);
qsort(s, sz, sizeof(s[0]), cmp_stu_by_age);
}
int main() {
test();
return 0;
}
?一样的配方,一样的味道
模拟实现qsort
模拟qsort对数组的排序全代码
//模拟qsort对数组的排序
#include<stdio.h>
int cmp_int(const void* e1, const void* e2)
{
return (*(int*)e1 - *(int*)e2); //直接返回
//这是升序排序,当我们想要降序判刑只要交换e1、e2的位置就行了,逻辑交换
}
void Swap(char* buf1, char* buf2, int width)
{
int i = 0;
for (i = 0; i < width; i++)
{
char tmp = *buf1;
*buf1 = *buf2;
*buf2 = tmp;
*buf1++;
*buf2++;
}
}
//基于冒泡排序的思想实现qsort
void bubble_sort(void* base, int sz, int width, int (*cmp)(const void*e1, const void*e2))
{
int i = 0;
//趟数
for (i = 0; i < sz - 1; i++)
{
int flag = 1;
//交换
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);
flag = 0;
}
}
if (flag)
{
break;
}
}
}
int main() {
int arr[] = { 9,8,7,6,5,4,3,2,1,0 };
//升序排序
int sz = sizeof(arr) / sizeof(arr[0]);
//冒泡排序模拟qsort
bubble_sort(arr, sz, sizeof(arr[0]), cmp_int);
int i = 0;
for (i = 0; i < sz; i++)
{
printf("%d ", arr[i]);
}
printf("\n");
return 0;
}
解析
主函数
int main() { ?? ?int arr[] = { 9,8,7,6,5,4,3,2,1,0 }; ?? ?//升序排序 ?? ?int sz = sizeof(arr) / sizeof(arr[0]);
?? ?//冒泡排序模拟qsort ?? ?bubble_sort(arr, sz, sizeof(arr[0]), cmp_int);? //这里毋庸置疑是把数组首元素的地址、
?? ?int i = 0;? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?//元素个数、元素字节大小和一个比较函数的地址 ?? ?for (i = 0; i < sz; i++)? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? //传给了我们自定义的函数bubble_sort ?? ?{ ?? ??? ?printf("%d ", arr[i]); ?? ?} ?? ?printf("\n"); ?? ?return 0; }?
比较函数
int cmp_int(const void* e1, const void* e2)
{
return (*(int*)e1 - *(int*)e2); //直接返回
//这是升序排序,当我们想要降序判刑只要交换e1、e2的位置就行了,逻辑交换
}
交换函数
void Swap(char* buf1, char* buf2, int width)? ?//接收数据的宽度,这样在下面的循环中就可以 {? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?//保证正常循环不溢出 ?? ?int i = 0; ?? ?for (i = 0; i < width; i++)?//需要注意的是这里是字节的交换哦,全部字节交换也就是数据交换 ?? ?{ ? ? ? ? ? ? ? ? ? ? ? ? ? ? ??????//在一开始我们是默认不知道传过来的数据是什么类型的 ?? ??? ?char tmp = *buf1;? ?//因此我们使用char类型开始,这样什么类型的开始都可以向后找到 ?? ??? ?*buf1 = *buf2;? ? ? ?? ?? ??? ?*buf2 = tmp; ?? ??? ?*buf1++; ?? ??? ?*buf2++; ?? ?} }?
基于冒泡排序的思想实现qsort的函数
void bubble_sort(void* base, int sz, int width, int (*cmp)(const void* e1, const void* e2)) { ?? ?int i = 0; ?? ?//趟数 ?? ?for (i = 0; i < sz - 1; i++) ?? ?{ ?? ??? ?int flag = 1; ?? ??? ?//交换 ?? ??? ?int j = 0; ?? ??? ?for (j = 0; j < sz - 1 - i; j++) ?? ??? ?{ ?? ??? ??? ?if (cmp((char*)base + j * width, (char*)base + (j + 1) * width) > 0) ?? ??? ??? ?{? ? ? //这里将它转为为chaf*类型的指针,再加上元素位置乘以一个宽度,这样就可以 ?? ??? ??? ??? ?//交换? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? //找到对应的元素了 ?? ??? ??? ??? ?Swap((char*)base + j * width, (char*)base + (j + 1) * width, width); ?? ??? ??? ??? ?flag = 0;? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? //这里记得把宽度传过去,便于后面交换 ?? ??? ??? ?} ?? ??? ?} ?? ??? ?if (flag) ?? ??? ?{ ?? ??? ??? ?break; ?? ??? ?} ?? ?} }?
排序结构体数据
?
#include<stdio.h>
#include<string.h>
struct Stu
{
char name[20];
int age;
};
int cmp_int(const void*e1, const void*e2)
{
return ( *(int*)e1 - *(int*)e2 ); //直接返回
//这是升序排序,当我们想要降序判刑只要交换e1、e2的位置就行了,逻辑交换
}
cmp_stu_by_name(const void* e1, const void* e2)
{
return strcmp(((struct Stu*)e1)->name, ((struct Stu*)e2)->name);
}
cmp_stu_by_age(const void* e1, const void* e2)
{
return ((struct Stu*)e1)->age - ((struct Stu*)e2)->age;
}
void Swap(char*buf1, char*buf2, int width)
{
int i = 0;
for ( i = 0; i < width; i++)
{
char tmp = *buf1;
*buf1 = *buf2;
*buf2 = tmp;
*buf1++;
*buf2++;
}
}
//基于冒泡排序的思想实现qsort
void bubble_sort(void *base, int sz,int width,int (*cmp)(const void* e1 , const void* e2))
{
int i = 0;
//趟数
for ( i = 0; i < sz-1; i++)
{
int flag = 1;
//交换
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);
flag = 0;
}
}
if (flag)
{
break;
}
}
}
void test()
{
//qsort来排序结构体数据
struct Stu s[] = { {"zhangsan",15}, {"lisi",30}, {"wangwu",25} };
int sz = sizeof(s) / sizeof(s[0]);
bubble_sort(s, sz, sizeof(s[0]), cmp_stu_by_age);//如果按名字排序,改函数名字就可以了
} //cmp_stu_by_name
int main() {
//结构体排序
test();
return 0;
}
?
结果
按年龄
?按姓名
?结束语
? ? ? ? ????????????????????????四年
四年很快啊,暮然之际已经过去一年了,我进入学习编程也已经一个学期半年时光了,用这个记录自己学习的时光,以后就可以回顾这些记忆了……
未完持续更新中……?
|