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

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

时间:2024-08-16 16:51:45浏览次数:10  
标签:sz int void qsort 冒泡排序 char width 库函数

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

文章目录


前言

【萌新学习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*如何进行使用。

标签:sz,int,void,qsort,冒泡排序,char,width,库函数
From: https://blog.csdn.net/2302_77182146/article/details/141252401

相关文章

  • 冒泡排序算法
    C++实现冒泡排序算法:#include<iostream>usingnamespacestd;voidbubbleSort(intarr[],intn){for(inti=0;i<n-1;i++){for(intj=0;j<n-i-1;j++){if(arr[j]>arr[j+1]){//交换arr[j]和arr[j+1]inttemp=arr[j];arr[j]=arr[j+1];......
  • 进阶 Java冒泡排序递归法 有点难度哦
    简介这里有用到递归的冒泡排序思路,难度对新手很大,不明白递归和冒泡排序的小伙子可以先看看我的其他两个文章。连接在这里:Java冒泡排序https://blog.csdn.net/ouhexie/article/details/140985984?spm=1001.2014.3001.5501Java递归算法https://blog.csdn.net/ouhexie/articl......
  • QSortFilterProxyModel和QTreeView排序功能
    1、需求,创建一个树有多层结构,同一层按照插入顺序逆序排列; ui.treeView->setHeaderHidden(true);//treewidget头标题是否显示,此处隐藏标题//ui.treeWidget->header()->setHorizontalScrollMode(QAbstractItemView::ScrollPerPixel);ui.treeView->header()->s......
  • 冒泡排序(JAVA)
    冒泡排序的过程排序次数是外层循环(5-1)交换次数是内层循环(5-i-1)importjava.util.Scanner;publicclassMain{publicstaticvoidmain(String[]args){intarr[]=newint[5];inttemp;System.out.println("请输入5名学生的成绩......
  • 常见 字符串库函数 的使用与模拟实现 #strlen #strcpy #strcat #strcmp#strstr #strto
    文章目录前言路漫漫其修远兮,吾将上下而求索。在C语言之中,提供了字符类型,也有字符串的概念,但是却并没有字符串的类型。没有类型就不方便操作,于是乎就提供了一系列的字符串函数来支持对字符串的操作;一、求字符串长度strlen专门用来求字符串长度的函数size_t strl......
  • C++标准库函数
    很多人用C++就是因为C++有很多方便的函数,所以我来科普一下方便的输入输出函数:scanf(); 高效的输入(TLE的可以和printf一起用,很快!)格式:输入变量a:scanf(...,&a);一定要加&(取地址)...是按a的类型来定的:%d:int%lld:longlong%lf:double%c:charprintf(); ......
  • 排序简单篇——冒泡排序、选择排序、插入排序、希尔排序、快速排序全解析【附完整源码
    ......
  • C语言 | printf、scanf及库函数
    目录一、关于printf和scanf1、输入输出的概念2、语句2.1printf()函数2.2.1print输出格式2.2.2占位符  2.2.3限定宽度2.2.3.1对于小数以外的2.2.3.2对于小数2.2.4显示符号2.2scanf()函数2.2.1基本用法2.2.2基本格式2.2.3限定宽度2.2.4scanf的返回......
  • C:冒泡排序
    1、冒泡排序介绍:冒泡排序的核心思想就是:两两相邻的元素进行比较。先用一个例子来帮助大家理解一下冒泡排序的算法是怎们进行的有一排高矮不同的人站成一列,要按照从矮到高的顺序重新排队。冒泡排序的方法就是,从第一个人开始,依次两两比较相邻的两个人的身高。如果左边的人比......
  • 利用指针来升序数组,(冒泡排序)
    我们写完数组后,通过写函数来是代码清晰明了,第一个升序函数,通过传入arr与len,再用冒泡排序的方法即可将数组升序,这里注意,传入arr,也就是数组的首地址,函数用Int*arr接受,这里传入首地址,也就是指针的方法,这个首地址(指针)允许函数内部通过数组索引的方法来访问数组中的其他元素,......