目录
1 冒泡排序实现
实现一个冒泡排序函数,思路:两两相邻元素比较,如果不满足顺序就交换。
例如,对int arr[10]={9,8,7,6,5,4,3,2,1,0};进行冒泡排序,产生一个升序的数组。
以此类推,10个元素进行9趟排序,n个元素进行n-1趟排序。
代码实现:
#include <stdio.h>
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 + 1] < arr[j])
{
flag = 0;
int temp = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = temp;
}
}
if (flag == 1)
{
break;
}
}
}
int main()
{
int arr[10] = { 9,8,7,6,5,4,3,2,1,0 };
int sz = sizeof(arr) / sizeof(arr[0]);
Bubble_sort(arr, sz);
for ( int i = 0; i < sz; i++)
{
printf("%d ", arr[i]);
}
printf("\n");
return 0;
}
代码中的函数只能排序整型数组,这样就有局限性,这就引出了qsort函数。
2 qsort函数
qsort是用来排序的库函数,qsort函数可以排序任意类型的数据。使用时要用头文件<stdlib.h>
void qsort (void* base, size_t num, size_t size, int (*compar)(const void*,const void*));
这个函数有4个参数
1 void* base是指针,指向的是待排序的数组的第一个元素
2 size_t num是base指向的待排序数组的元素个数
3 size_t size是base指向的待排序数组的元素大小
4 int (*compar)(const void*,const void*)是函数指针,指向的是两个元素的比较函数,比较函数用来比较两个数的函数大小,这个是根据不同类型数组进行排序时,由我们自行编写的。
如图,比较函数参数中的两个指针p1和p2,返回一个小于0的数字,p1排在p2前面; 返回一个大于0的数字,p2排在p1前面;如果相等,则返回0,那么我们就可以编写一段代码来使用以下qsort函数:
//一、qsort排列整型数据
#include <stdio.h>
#include <stdlib.h>
int int_cmp(const void* p1,const void* p2)
{
return (*(int*)p1 - *(int*)p2);
}
int main()
{
int arr[10] = { 9,8,7,6,5,4,3,2,1,0 };
int sz = sizeof(arr) / sizeof(arr[0]);//计算数组长度
qsort(arr, sz, sizeof(arr[0]), int_cmp);
int i = 0;
for (i = 0; i < sz; i++)
{
printf("%d ", arr[i]);
}
printf("\n");
return 0;
}
输出结果:
比较函数
int int_cmp(const void* p1,const void* p2)
{
return (*(int*)p1 - *(int*)p2);
}这里的两个参数是固定的,我们要排序的序列是9 8 7 6 5 4 3 2 1 0,那么这两个指针指向的是整型类型的数据,而p1,p2是void*类型的指针,所以需要先进行强制类型转换,再做差,大于0时交换两个数据。这样再使用语句qsort(arr, sz, sizeof(arr[0]), int_cmp);就能把一个杂乱的数组排序成升序。
如果要排列成降序呢?
只需要改变函数的逻辑:
int int_cmp(const void* p1,const void* p2)
{
return (*(int*)p2 - *(int*)p1);
}意义就是后一个数大于前一个数,交换两个数字。返回一个大于0的数字,p2排在p1前面。
#include <stdio.h>
#include <stdlib.h>
int int_cmp(const void* p1,const void* p2)
{
return (*(int*)p2 - *(int*)p1);
}
int main()
{
int arr[10] = { 8,7,9,6,5,3,1,4,2,0 };
int sz = sizeof(arr) / sizeof(arr[0]);//计算数组长度
qsort(arr, sz, sizeof(arr[0]), int_cmp);
int i = 0;
for (i = 0; i < sz; i++)
{
printf("%d ", arr[i]);
}
printf("\n");
return 0;
}
输出结果,排列成降序:
再举一个例子。利用qsort排序结构体的数据:
//二、使用qsort实现结构体排序
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
struct Stu
{
char name[20];
int age;
};
int cmp_stu_by_name(const void* p1, const void* p2)
{
return strcmp(((struct Stu*)p1)->name, ((struct Stu*)p2)->name);
}
int cmp_stu_by_age(const void* p1, const void* p2)
{
return (((struct Stu*)p1)->age - ((struct Stu*)p2)->age);
}
int main()
{
struct Stu arr[3] = { {"zhang san",20},{"li si",30},{"wang wu",40}};
int sz = sizeof(arr) / sizeof(arr[0]);
qsort(arr, sz, sizeof(arr[0]), cmp_stu_by_name);//按照名字排序
qsort(arr, sz, sizeof(arr[0]), cmp_stu_by_age);//按照年龄排序
return 0;
}
3 qsort函数的模拟实现
#include <stdio.h>
#include <stdlib.h>
int cmp_int(const void* p1, const void* p2)
{
return (*(int*)p1 - *(int*)p2);
}
void Print_arr(int* arr, int sz)
{
int i = 0;
for (i = 0; i < sz; i++)
{
printf("%d ", arr[i]);
}
printf("\n");
}
void swap(char* buf1,char* buf2,size_t width)
{
int i = 0;
for (i = 0; i < width; i++)
{
char temp = *buf1;
*buf1 = *buf2;
*buf2 = temp;
buf1++;
buf2++;
}
}
void bubble_sort(char* base, size_t sz, size_t width, int(*cmp)(const void* p1, const void* p2))
{
int i = 0;//趟数
for (i = 0; i < sz - 1; i++)
{
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);
}
}
}
}
int main()//模拟实现qsort函数
{
int arr[10] = { 9,7,8,6,3,5,4,1,2,0 };
int sz = sizeof(arr) / sizeof(arr[0]);
bubble_sort(arr, sz, sizeof(arr[0]), cmp_int);
Print_arr(arr,sz);
return 0;
}
代码结构
cmp_int:用于比较两个整数的函数(升序),小于0时是降序
Print_arr:打印整型数组
swap:交换两个内存块的内容(按每个字节交换)
bubble_sort:通用的冒泡排序函数,支持任意数据类型。
交换函数
void swap(char* buf1,char* buf2,size_t width)
{
int i = 0;
for (i = 0; i < width; i++)
{
char temp = *buf1;
*buf1 = *buf2;
*buf2 = temp;
buf1++;
buf2++;
}
}逐字节交换 buf1 和 buf2 指向的 width 字节内存。使用char* 是因为char 是 1 个字节,可以处理任意数据类型(如 int、struct 等)。
通用冒泡排序函数
void bubble_sort(char* base, size_t sz, size_t width, int(*cmp)(const void* p1, const void* p2))
{
int i = 0;//趟数
for (i = 0; i < sz - 1; i++)
{
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);
}
}
}
}
参数:
base:数组首地址,转换为 char* 以便按字节计算偏移,满足通用性。
sz:元素个数。
width:每个元素的字节大小。
cmp:比较函数指针。
逻辑:通过 base + j * width 计算第 j 个元素的地址。调用 cmp 比较相邻元素。如果 cmp 返回 > 0,调用 swap 交换内存内容。
以上就是这篇文章的全部内容了,如果这篇文章对你有用,可以点点赞哦,你的支持就是我写下去的动力,后续会继续分享更多的知识。