【萌新学习C语言】如何根据qsort库函数,写一个能给任何类型排序的冒泡排序。

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档


前言

【萌新学习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新版冒泡排序与整型冒泡排序的区别

  1. 新版冒泡排序与整型冒泡排序最大的不同就是判断语句以及对数据进行交换的时候。
  2. 新版冒泡排序:你不知道使用者使用冒泡排序是要排序整数还是结构体等等,所以函数参数选择的void* base。无类型参数可以放各种类型的参数,其使用无类型指针是不能直接使用需要进行强制类型转化才行,也不能对无类型指针进行加减操作。
  3. 进行判断时,因为不知使用者到底要传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)函数就能进行比较。
  4. 判断完后就开始进行交换,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*如何进行使用。

  • 20
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
C语言数组排序函数qsort是标准库函数,用于对数组进行排序。它的使用方法是通过传入一个比较函数来指定排序的规则。在给出的代码中,我们可以看到使用qsort函数对一个整型数组进行升序排序的例子。\[1\] 为了实现qsort函数的功能,我们可以使用一种较为简单的排序算法,比如冒泡排序算法来模拟实现一个具有排序数组、字符串、结构体等功能的bubble_sort函数。\[2\]这个函数的参数可以仿照qsort函数的参数,包括要排序的数组的起始地址、元素个数、每个元素的大小以及一个比较函数。\[3\] 具体实现bubble_sort函数的函数体可以根据冒泡排序算法来编,通过比较相邻的元素并交换位置来实现排序排序的规则可以通过比较函数来指定,根据需要可以实现升序或降序排序。 总结起来,qsortC语言标准库中的数组排序函数,可以通过传入比较函数来指定排序规则。如果想要模拟实现类似功能的排序函数,可以使用一种简单的排序算法,比如冒泡排序,并根据需要实现相应的比较函数。 #### 引用[.reference_title] - *1* *2* *3* [【C语言qsort()函数详解:能给万物排序的神奇函数](https://blog.csdn.net/weixin_72357342/article/details/130628874)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control_2,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值