1.冒泡排序
对数据排序的方式有很多
冒泡排序
选择排序
插入排序
快速排序
。。。
qsort是回调函数的案例
qosrt—是一个库函数,底层使用的快速排序的方式来对数据进行排序
这个函数可以直接使用(#include<stdlib.h>)
这个函数可以用来排序任意类型的数据
1.1冒泡排序的思想
冒泡排序的思想,两两相邻的元素进行比较
#include<stdio.h>
void bubble_sort(int arr[],int sz)
{
int i = 0;
int j = 0;
for (i = 0; i < sz - 1; i++)
{
for (j = 0; j < sz - 1 - i; j++)
{
if (arr[j] > arr[j + 1])
{
int tem = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = tem;
}
}
}
}
void print(int arr[], int sz)
{
int i = 0;
for (i = 0; i < sz; i++)
{
printf("%d ", arr[i]);
}
printf("\n");
}
int main()
{
int arr[] = { 1,3,4,6,7,8,9,2,5,0 };
int sz = sizeof(arr) / sizeof(arr[0]);
print(arr, sz);
bubble_sort(arr,sz);
print(arr,sz);
return 0;
}
一组数据,两两相比,如果前面的大于后面的数就进行交换(升序),那么我们要对假如10个数据来进行比较,我们先让一个数与后面的进行比较,假设这个数是最大的,我们需要多少比几组呢?
答:是10-1组;这样走一趟后我们还剩下9个数,这九个数再一次向后比较,一共需要多少趟呢?
答:是9趟;那么我们每走完一趟,之前的那个数就会比如说10,已经是最大的了就不需要比较了,那么每次比一趟,我们比的次数就会减一。
void bubble_sort(int arr[],int sz)
{
int i = 0;
int j = 0;
for (i = 0; i < sz - 1; i++)//冒泡排序的趟数
{
for (j = 0; j < sz - 1 - i; j++)//一趟冒泡排序
{
if (arr[j] > arr[j + 1])
{
int tem = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = tem;
}
}
}
}
2.qsort库函数的使用方法
qsort是一个库函数,头文件使用是#include<stdlib.h>
是quick sort 的缩写(快排)。
我们可以打开网站,然后点击legacy version,搜索qsortcplusplus.comhttps://cplusplus.com/
我们可以看到如下界面,里面描述,qsort函数需要的参数
void qsort (void* base, size_t num, size_t size, int (*compar)(const void*,const void*));
2.1void* 类型介绍
我们之前学到,每一种数据类型都有相对应的类型指针,如char类型是char*指针
int类型是int*指针;那么void*是什么意思呢?
答:void*类似一个垃圾站可以接收任意类型的指针。
void*的性质:1.void*可以接收任意的指针;2.void*不能解引用(因为他不是任何类型,我们解引用不知道读取几个字节的数据)
qsort库函数,是可以处理任意类型的函数,他接收指针类型也必须是任意类型所以用到了void*。
2.2qosrt函数的使用
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 (*comper)(const void*,const void*)这个的意思是,
要我们自己给出一个可以比较数组中元素的函数,并把函数的指针传过来(因为我们要进行比较的内容只有我们自己知道,计算机并不能直接读取)。并且这个函数的返回类型是int 而且函数的参数是2个void*。
下面我们来使用这个函数:
int main()
{
int arr[10] = { 5,4,2,1,3,0,9,8,7,6 };//我们先使用比较简单的数据,一个乱序的整形数组
int sum = sizeof(arr) / sizeof(arr[0]);//我们得到他的元素个数
int size = sizeof(arr[0]); //我们得到他每个元素的大小
qsort(arr, sum, sizeof(arr[0]),?);
//依次填入:数组开始的地址(也就是数组名)
//数组元素个数
//数组的元素大小
//比较数组中2个元素的函数?
return 0;
}
上面的代码里我们已经填入了要求我们的数据,那么还有一个函数该怎么写呢?
这里我们明确知道的是比较两个整形,整形数据该怎么比较呢?
函数的参数是两个void*该怎么比较呢?
我们一一来解决
函数的参数是两个void*该怎么比较呢?答:
我们的比较函数并不是要真实的传入2个数据,而是对某一种类型进行比较,所以我们可以对void*进行强制类型转换把其转换为(int*),再对其解引用。
我们来写这个简单的函数
int cmp_int(const void* e1, const void*e2)
{
return *(int*)e1 - *(int*)e2;
}
这样我们就可以轻松使用了;
3.模拟实现qsort
摸拟原码如下:
#include<string.h>
#include<stdio.h>
struct stu
{
char name[20];
int age;
};
void swp( char* e1, char* e2 ,int sz)//交换函数,我们不能确定比较2个数据的大小,因为我们传入的类型是char*,所以我们需要再传入一个数据大小的参数
{
int i = 0;
for (i = 0; i < sz; i++)
{
char tmp = *e1;
*e1 = *e2;
*e2 = tmp;
e1++;
e2++;
}
}
//一个首元素的指针 //这个数组的元素个数
void qsort(void* base, size_t sum, size_t size, int (*cmp)(const void* e1, const void* e2)) //qsort函数,底层逻辑是冒泡排序
{ // 这数组每个元素的大小 //需要使用者自己设计一个比较元素大小的函数,并传给这个函数指针
int i = 0;
for (i = 0; i < sum - 1; i++)//冒泡排序的每一趟
{
int j = 0;
for (j = 0; j < sum - 1 - i; j++)//冒泡排序,每一趟的每一对的交换
{
// 因为这个函数开头要求了一个判断函数指针,所以我们直接使用就好了
//不管你什么类型,传过去都改为char*类型的指针,因为我们要适配所有类型;
//改成char*类型的好处就是,我们还知道数据的大小,就可以跳过该数据的大小来进行比较
//就可以比较任意类型的数据了
if (cmp((char*)base + size * j, (char*)base + size * (j+1)) > 0)
{
swp((char*)base + size * j, (char*)base + size * (j + 1), size);//因为我们不知道这个类型,并且我们强制转换成为了char类型,如果大于这个类型,我们该怎么办?
//所以我们交换的时候,要把这个类型大小加进去 这样我们再把这一个类型范围内所有数据都交换
//
}
}
}
}
void print(int arr[],int sz)
{
int i = 0;
for (i = 0; i < sz; i++)
{
printf("%d ", arr[i]);
}
printf("\n");
}
int cmp_int(const void* e1, const void*e2)//e1是一个指针,存放了要比较元素的地址
{ //e2是一个指针,存放了要比较元素的地址
return *(int*)e1 - *(int*)e2;
}
int cmp_age(const void* e1, const void* e2)
{
return ((struct stu*)e1)->age - ((struct stu*)e2)->age;
}
int cmp_name(const void* e1, const void* e2)
{
return strcmp(((struct stu*)e1)->name, ((struct stu*)e2)->name);
}
void test1()
{
int arr[10] = { 5,4,2,1,3,0,9,8,7,6 };
int sum = sizeof(arr) / sizeof(arr[0]);
int size = sizeof(arr[0]);
print(arr,sum);
qsort(arr, sum, sizeof(arr[0]), cmp_int);
print(arr,sum);
}
void test2()
{
struct stu arry[3] = { {"zhang",14},{"li",11},{"ma",10} };
int sum2 = sizeof(arry) / sizeof(arry[0]);
int size2 = sizeof(arry[0]);
qsort(arry, sum2, sizeof(arry[0]), cmp_name);
}
int main()
{
test1();
test2();
return 0;
}