(Hello小伙伴们大家好呀,今天我们来回顾一下快速排序,在此之前让我们一起回忆 一下冒泡排序吧。)
一.冒泡排序
什么是冒泡排序呢?
我们可以简单的理解为两个两两相邻的元素进行比较,最终排成升序或降序,以升序为例如果较前的数大于较后的数(在数组范围内) ,那进行交换以此类推。
如图所示:(最后0是不需要排,在9位数拍好后0自然而然就排到了第一位)
代码思想:
#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
//模拟实现冒泡排序
void bubble_sort(int str[], int sz)
{
int i = 0;
for (i = 0; i < sz; i++)//排几趟
{
int j = 0;
for (j=0;j<sz-1-i;j++)//一趟多少次
{
if (str[j] > str[j + 1])
{
int tmp = str[j];
str[j] = str[j + 1];
str[j + 1] = tmp;
}
}
}
}
void print_arr(int str[], int sz)
{
int i = 0;
for (i = 0; i < sz ; i++)
{
printf("%d ", str[i]);
}
printf("\n");
}
int main()
{
int arr[] = { 9,8,7,6,5,4,3,2,1,0 };
int sz = sizeof(arr) / sizeof(arr[0]);
print_arr(arr, sz);
bubble_sort(arr, sz);
print_arr(arr, sz);
return 0;
}
二.qsort函数模拟实现
(在写好冒泡排序后,我们发现一些缺陷,参数是固定的,只能是整数类型,并不通用。
最终找到qsort函数它是用来排序任何类型的数据)
(一).qsort函数的详解:
1.qsort函数的原型:
void qsort (void* base,
size_t num,
size_t size,
int (*compar)(const void*,const void*)
);
有四个参数
(1). base:指针指向待排序数组的第一个元素
void*base:只不过被转化为void*类型的指针也就是说传给qsort待排序数组的第一个元素的地址(起始地址)。也就穿个数组名即可。
(2).size_t num:待排序数组的元素个数
(3).size_t size:待排序数组中每个数组的每个元素的大小(字节)
sizeof来计算即可。
(4).int (*compar)(const void*,const void*):首先这是一个函数指针,函数指针cmp指向的是一个函数,这个函数是用来比较两个元素的大小。
由于它可以排序任何类型,不同类型比较有所差异
排序整型数组:做差使用>比较
排序结构体数组:可能不能用>比较,因为要根据成员,例如年龄可以用>,姓名因为是字符我们可以用strcmp比较
(5).两个复杂类型的数据进行比较,方法不同。
我们可以可以把cmp单独拿出来,自己提供比较的方法。
(6).头文件:#include<stdlib.h>
(二).void *的理解:
Void*指针,它不能够进行解引用,因为对它解引用操作它也不知道访问多少个字节,也不能+-整数的操作
Void*类型的指针是用来任意类型数据的地址,就像个垃圾桶。
(三).qsort函数代码实现:
1.整型比较
void print_arr(int str[], int sz)
{
int i = 0;
for (i = 0; i < sz; i++)
{
printf("%d ", str[i]);
}
printf("\n");
}
//测试qsort两个整型比较
#include<stdlib.h>
int cmp_int(const void* e1, const void* e2)
{
//e1,e2存放的是需要比较两个元素的地址
//整型比较,强制转换 (int*)e1先强转,*(int*)e1再解引用
return *(int*)e1 - *(int*)e2;
//有三种结果 >0返回>0的数 =0返回0 <0返回<0的数
}
void test1()
{
int arr[] = { 9,8,7,6,5,4,3,2,1,0 };
int sz = sizeof(arr) / sizeof(arr[0]);
print_arr(arr, sz);
qsort(arr,//数组名首元素的地址
sizeof(arr) / sizeof(arr[0]),//元素个数
sizeof(arr[0]),//一个元素大小
cmp_int //整型比较的函数,自己提供,返回类型一致
);
print_arr(arr, sz);
}
int main()
{
test1();
return 0;
}
2.测试qsort排序结构体数据
(1)对名字进行比较
struct stu
{
char name[20];
int age;
};
//比较名字
#include<stdlib.h>
#include<string.h>//strcmp
int cmp_stu_by_name(const void* e1, const void* e2)
{
//先强制类型转换再结构体指向成员
//比较的是两个字符串的大小,用strcmp
//strcmp返回类型为Int和qsort一样直接返回
return strcmp(((struct stu*)e1)->name, ((struct stu*)e2)->name);
}
void test2()
{
struct stu arr[] = { {"zhangsan",18},{"lisi",2},{"wangwu",24} };//结构体数组,学生信息
int sz = sizeof(arr) / sizeof(arr[0]);
qsort(arr,//数组名首元素的地址
sizeof(arr) / sizeof(arr[0]),//元素个数
sizeof(arr[0]),//一个元素大小
cmp_stu_by_name
);
}
int main()
{
//test1();
test2();
return 0;
}
(2)年龄进行比较
struct stu
{
char name[20];
int age;
};
//比较年龄
int cmp_stu_by_age(const void* e1, const void* e2)
{
//比较的是两个整型的大小,做差
return( (struct stu*)e1)->age- ((struct stu*)e2)->age;
}
void test3()
{
struct stu arr[] = { {"zhangsan",18},{"lisi",2},{"wangwu",24} };//结构体数组,学生信息
int sz = sizeof(arr) / sizeof(arr[0]);
qsort(arr,//数组名首元素的地址
sizeof(arr) / sizeof(arr[0]),//元素个数
sizeof(arr[0]),//一个元素大小
cmp_stu_by_age
);
}
int main()
{
//test1();
//test2();
test3();
return 0;
}