提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档
文章目录
前言
【萌新学习C语言】如何根据qsort库函数,写一个能给任何类型排序的冒泡排序。
提示:以下是本篇文章正文内容,下面案例可供参考
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
所用到的库函数
一、sqort函数
1.1qsort函数定义
如图:
在上图可以看出qsort函数的使用依赖于<stdlib.h>这个库,其还需要四个参数
void*base - (数据的地址),size_t num - (数据的个数), size_t width - (数据的宽度也就是单个数据所占的字节大小),int(compare)(const void elem1,const void* elem2) - (比较函数)
1.2qsort如何使用函数使用
1.2.1用qsort函数,将结构体类型的name进行排序
s为结构体的地址
sz为结构体数组的个数
sizeof[s[0]]为结构体一个成员的大小,cmp_Stu_bu_name为比较成员为name的大小其单位为字节
struct Stu
{
char name[20];
int age;
};
int cmp_Stu_by_name(const void* e1, const void* e2)
{
return strcmp(((struct Stu*)e1)->name, ((struct Stu*)e2)->name);
}
void test2()
{
struct Stu s[] = { {"zhangsan",25},{"lisi",20},{"wangwu",30}};
int sz = sizeof(s) / sizeof(s[0]);
qsort(s, sz, sizeof(s[0]), cmp_Stu_by_name);
}
int main()
{
//test1();
test2();
return 0;
}
交换前:
交换后:
1.2.2用qsort函数,将结构体类型的age进行排序
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 s[] = { {"zhangsan",25},{"lisi",20},{"wangwu",30} };
int sz = sizeof(s) / sizeof(s[0]);
qsort(s, sz, sizeof(s[0]), cmp_Stu_by_age);
}
int main()
{
//test1();
//test2();
test3();
return 0;
}
排序前:
排序后:
二、整数型的冒泡排序
2.1冒泡排序思想
冒泡排序的核心思想是相邻两个数进行比较。
假设有一个数组int arr[ ]={9,8,7,6,5,4,3,2,1,0};
进行升序排列,就用9跟8进行比较9大就和8进行交换,然后9再和7进行比较,还是9大进行交换。直到9到0的位置上才结束第一趟排序,第一趟9比较了10-1次,第二趟8比较了10-2次,所以第n趟10-1-i(这里的i是for(i=0;i<sz-1;i++))。
代码如下(示例):
void bubble_sort(int arr[], int sz)
{
int i = 0;
for (i = 0; i < sz - 1; i++)
{
int j = 0;
int flag = 1;
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 == 1)
{
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;
}
运行结果如下图
三.所有类型都适用的冒泡排序
整型冒泡排序:void bubble_sort(int arr[], int sz);
qsort函数排序:void qsort( void *base, size_t num, size_t width, int (__cdecl *compare )(const void *elem1, const void *elem2 ) );
根据qsort函数,我们可以将冒泡排序改为:
void bubble_sort(void *base,int sz,int width,int(*cmp)(const void *e1,const void *e2));其冒泡排序的基本逻辑不变,要变的是判断条件。
3.1新版冒泡排序与整型冒泡排序的区别
- 新版冒泡排序与整型冒泡排序最大的不同就是判断语句以及对数据进行交换的时候。
- 新版冒泡排序:你不知道使用者使用冒泡排序是要排序整数还是结构体等等,所以函数参数选择的void* base。无类型参数可以放各种类型的参数,其使用无类型指针是不能直接使用需要进行强制类型转化才行,也不能对无类型指针进行加减操作。
- 进行判断时,因为不知使用者到底要传int 型的还是char型的,所以要把voidbase进行强制类型转化成char类型的这样即使使用者传的是int型我们也可以对已经强制类型转化的base进行加上j*width(这里的width为4)
(char*)base+j*width
这样也就是一个整型的长度,对base进行加上(j+1)*width这样就是下一个整型的地址(char*)base+(j+1)*width)
,就通过使用者写的int cmp_int(const void* e1, const void* e2)
函数就能进行比较。 - 判断完后就开始进行交换,
Swap((char*)base + j * width, (char*)base + (j + 1) * width,width);
将首地址、下一个数据地址、宽度进行传参。假如使用者要对整型进行升序排列,这里的首地址和下一个数据地址也就是相邻的两个整数,只不过以char的形式进行,char进行加减只会加减一个字节,要想交换一个整数,就得交换4个字节,所以进行for (i = 0; i < width; i++)
。就这样进行交换。
新版冒泡排序:
代码如下(示例):
int cmp_int(const void* e1, const void* e2)
{
return (*(int*)e1) - (*(int*)e2);
}
void Swap(char* buf1, char* buf2, int width)
{
int i = 0;
for (i = 0; i < width; i++)
{
int tmp = *buf1;
*buf1 = *buf2;
*buf2 = tmp;
buf1++;
buf2++;
}
}
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 j = 0;
int flag = 1;
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 == 1)
{
break;
}
}
}
整数型冒泡排序:
代码如下:
void bubble_sort(int arr[], int sz)
{
int i = 0;
for (i = 0; i < sz - 1; i++)
{
int j = 0;
int flag = 1;
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 == 1)
{
break;
}
}
}
3.2新版冒泡排序对整数排序
代码如下:
void Swap(char* buf1, char* buf2, int width)
{
int i = 0;
for (i = 0; i < width; i++)
{
int tmp = *buf1;
*buf1 = *buf2;
*buf2 = tmp;
buf1++;
buf2++;
}
}
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 j = 0;
int flag = 1;
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 == 1)
{
break;
}
}
}
int cmp_int(const void* e1, const void* e2)
{
return (*(int*)e1) - (*(int*)e2);
}
void test4()
{
int arr[] = { 9,8,7,6,5,4,3,2,1,0 };
int sz = sizeof(arr) / sizeof(arr[0]);
bubble_sort(arr,sz,sizeof(arr[0]),cmp_int);
int i = 0;
for (i = 0; i < sz; i++)
{
printf("%d ", arr[i]);
}
}
int main()
{
//test1();
//test2();
//test3();
test4();
return 0;
}
结果如下:
3.3新版冒泡排序对结构体类型排序
新版冒泡排序对结构体整型成员排序
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 Swap(char* buf1, char* buf2, int width)
{
int i = 0;
for (i = 0; i < width; i++)
{
int tmp = *buf1;
*buf1 = *buf2;
*buf2 = tmp;
buf1++;
buf2++;
}
}
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 j = 0;
int flag = 1;
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 == 1)
{
break;
}
}
}
void test5()
{
struct Stu s[] = { {"zhangsan",25},{"lisi",20},{"wangwu",30} };
int sz = sizeof(s) / sizeof(s[0]);
bubble_sort(s, sz, sizeof(s[0]), cmp_Stu_by_age);
}
int main()
{
//test1();
//test2();
//test3();
//test4();
test5();
return 0;
}
运行结果如下:
排序前:
排序后:
新版冒泡排序对结构体字符串成员排序
代码如下:
struct Stu
{
char name[20];
int age;
};
int cmp_Stu_by_name(const void* e1, const void* e2)
{
return strcmp(((struct Stu*)e1)->name, ((struct Stu*)e2)->name);
}
void Swap(char* buf1, char* buf2, int width)
{
int i = 0;
for (i = 0; i < width; i++)
{
int tmp = *buf1;
*buf1 = *buf2;
*buf2 = tmp;
buf1++;
buf2++;
}
}
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 j = 0;
int flag = 1;
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 == 1)
{
break;
}
}
}
void test6()
{
struct Stu s[] = { {"zhangsan",25},{"lisi",20},{"wangwu",30} };
int sz = sizeof(s) / sizeof(s[0]);
bubble_sort(s, sz, sizeof(s[0]), cmp_Stu_by_name);
}
int main()
{
//test1();
//test2();
//test3();
//test4();
//test5();
test6();
return 0;
}
运行结果如下:
排序前:
排序后:
总结
主要讲述了,如何将整型冒泡排序的方法改成能够对所有类型进行排序的冒泡方法,主要知识点有,对char指针加1和对int指针加1时的区别,void*如何进行使用。
标签:sz,int,void,qsort,冒泡排序,char,width,库函数 From: https://blog.csdn.net/2302_77182146/article/details/141252401