qsort函数的使用

一、qsort函数简介

  qsort是C语言中的一个库函数,它是基于快速排序算法实现的一个排序函数,qsort函数最大的特点就是它可以排任意类型的数据。

其使用方法如下:

void qsort( void *base, size_t num, size_t width, int (__cdecl *compare )(const void *elem1, const void *elem2 ) );

其中,参数说明如下:
base:存放的是待排序数据的起始位置
size_t num:数组中元素的个数。
size_t width:每个元素的大小,以字节为单位。
compar:指向一个比较函数的指针,该函数接受两个参数,分别是指向要比较的元素的指针,返回值为整型,表示两个元素的大小关系。
elem1与elem2是待比较的两个元素的地址
在这里插入图片描述
如果elem1 less than elem2返回小于0的数字
如果elem1 equivalent to elem2返回等于0的数字
如果elem1 greater than elem2返回大于0的数字

注:
  __cdecl *compareqsort 函数的回调参数,它指向一个函数,这个函数被 qsort 多次调用,用于排序数组中的元素。排序算法需要比较数组元素的大小关系,而比较大小关系的准则是由应用程序自身提供的,因此在调用 qsort 函数时,需要向qsort 函数提供一个指向比较函数的函数指针。compare 便是这个指针,它指向一个用户自定义的比较函数。比较函数只需要实现比较操作即可,并返回一个整数值,表示大小关系。在使用 qsort 函数时,需要将一个数组指针,数组元素的个数,元素的大小和一个指向比较函数的指针作为参数传递给 qsort 函数。当 qsort 排序时,会多次调用指向 compare 函数的指针,用于实现元素的比较和排序,最终将数组排序后返回给调用者。在 qsort 函数中,void *base 参数表示要排序的数组的首元素地址。具体来说,它是一个指向待排序数组的指针。该指针指向数组的第一个元素,qsort 函数通过该指针访问整个数组的元素。这个指针的类型为 void*,这意味着它可以指向任何类型的数据,同时也说明了 qsort 函数是一个通用的排序函数,可以对任何类型的数据进行排序。

  base 本身并不包含任何有关数组大小和元素类型的信息,这些信息需要通过其他参数(如 size_t nmembsize_t size)来提供。在使用 qsort 函数时,需要确保 base 指针指向包含足够元素数目的有效数组,否则可能会引起越界访问错误或未定义行为。

  在 qsort 函数中,const void *elem1 参数是一个指向数组中某一个元素的指针,它表示待排序的第一个元素。elem1 参数的类型为 const void*,它被声明为常量指针,这意味着函数不能修改指针所指向的值。这是因为,在排序过程中,qsort 函数不会更改数组的值,而只是通过调整元素的顺序来使数组变得有序。elem1 参数是由 qsort 函数以及比较函数自动传递给程序的,作为比较函数的输入,比较函数使用 elem1elem2 来比较数组元素的大小。需要注意的是,由于 elem1 参数被声明为常量指针,意味着在比较函数中不能修改它所指向的值。如果在比较函数中需要修改数组元素的值,则可以通过用类型转换来去掉 const 限定符,例如 (void*)elem1 可以将 const void* 类型转换为 void* 类型,这样指针所指向的值就可以修改了。但需要谨慎使用,必须确保修改指针所指向的值不会影响程序的正确性。

  elem2 参数的类型为 const void*,它被声明为常量指针,这意味着函数不能修改指针所指向的值。这是因为,在排序过程中,qsort 函数不会更改数组的值,而只是通过调整元素的顺序来使数组变得有序。elem2 参数是通过比较函数来定义的,该函数的作用是比较两个元素的大小。因此,elem2 参数实际上是由 qsort 函数以及比较函数自动传递给程序的。需要注意的是,由于 elem2 参数被声明为常量指针,因此如果在比较函数中需要修改数组元素的值,则不应该使用 const 关键字来声明参数。

二、qsort函数用法

1.qsort函数对整型数组排列

下面是一个示例程序,展示如何使用qsort函数对整数数组进行升序排列:
典例1:

#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
#include <stdlib.h>
void printf_arr(int arr[], int sz)
{
	int i = 0;
	for (i = 0; i < sz; i++)
	{
		printf("%d ", arr[i]);
	}
}

int cmp_int(const void* e1, const void* e2)
{
    //排序为升序
	return (*(int*)e1 - *(int*)e2); //*(int*)e1表示将e1强制类型转化为int*,return在这里返回大于0小于0或等于0的数
}

void test1()
{
	int arr[] = { 9,8,7,6,5,4,3,2,1,0 };
	int sz = sizeof(arr) / sizeof(arr[0]);
	//排序为升序
	qsort(arr, sz,sizeof(arr[0]),cmp_int);  //用qsort排整型
	printf_arr(arr, sz);
}


int main()
{
	test1();
	return 0;
}

运行结果:
在这里插入图片描述

典例2 :

#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
#include <stdlib.h>

int compare(const void *a, const void *b) {
    return (*(int*)a - *(int*)b);
}

int main() {
    int arr[] = {3, 1, 4, 1, 5, 9, 2, 6, 5, 3};
    int n = sizeof(arr) / sizeof(arr[0]);

    qsort(arr, n, sizeof(int), compare);

    printf("Sorted array: ");
    for (int i = 0; i < n; i++) {
        printf("%d ", arr[i]);
    }

    return 0;
}

运行结果:
在这里插入图片描述

  在这个示例程序中,我们定义了一个名为compare的比较函数,用于指定排序的方式。在主函数中,我们声明了一个整数数组,调用了qsort函数对其进行排序,并打印了排序后的结果。

2.qsort函数对结构体排列

下面是一个示例程序,展示如何使用qsort函数对整数数组进行升序排列:
典例1:

#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct Stu
{
	char name[20];
	int age;
	double score;
};

int com_stu_by_age(const void* elem1, const void* elem2)
{
    //升序打印
	return ((struct  Stu*)elem1)->age - ((struct Stu*)elem2)->age;
}
 
int com_stu_by_name(const void* elem1, const void* elem2)
{
	return strcmp(((struct  Stu*)elem1)->name , ((struct Stu*)elem2)->name);
	//升序打印
	//stringcmpare是按照字典的顺序来比较的,两个字符在比较的时候,比较的是它的ascll码值

}

void test1()
{
	struct  Stu arr[3] = { {"zhangsan",25,80.0},{"lisi",35,88.0},{"wangwu",22,96.0} };
	int sz = sizeof(arr) / sizeof(arr[0]);
	qsort(arr, sz, sizeof(arr[0]), com_stu_by_age);
	//qsort排序年龄打印结果22,25,35
	
	//qsort(arr, sz, sizeof(arr[0]), com_stu_by_name);
	//qsort排序年龄打印结果lisi,wangwu,zhangsan
	
}

int main()
{
	test1();
	return 0;
}

【注意】想要将升序改为降序,只需要将elem1与elem2的位置进行调换就行。

年龄调试结果:
在这里插入图片描述
姓名调试结果:
在这里插入图片描述

三、以qsort思想升级冒泡排序

1.冒泡排序整型数组

#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
int cmp(const void* elem1, const void* elem2)
{
	return (*(int*)elem1 - *(int*)elem2);
}
void Swap(char*buf1, char*buf2,int width)
{
	int i = 0;
	for (i = 0; i < width; i++)
	{
		char tmp = *buf1;
		*buf1 = *buf2;
		*buf2 = tmp;
		buf1++;
		buf2++;
	}
}

void bubble_sort(void*base, int num, int width, int(*cmp)( const void*elem1, const void*elem2 ))
{
	//计算行
	int i = 0;
	for (i = 0; i <num - 1; i++)  //计算冒泡排序的趟数
	{
		//计算列
		int j = 0;
		for (j = 0; j < num-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);
			}
		}    
		
	}
}

void print_sort(int arr[], int sz)
{
	int i = 0;
	for (i = 0; i < sz; i++)
	{
		printf("%d ", arr[i]);
	}
}

void test2()
{
	int arr[] = { 9,8,7,6,5,4,3,2,1 };
	//排序为升序
	int sz = sizeof(arr) / sizeof(arr[0]);
	bubble_sort(arr, sz, sizeof(arr[0]), cmp);
	print_sort(arr, sz);

} 

int main()
{
	test2();
	return 0;
}

运行结果:
在这里插入图片描述

2.冒泡排序结构体

排序姓名:

#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
#include <string.h>
struct Stu
{
	char name[20];
	int age;
	double score;
};

int cmp_stu_by_name(const void* elem1, const void* elem2)
{
	return strcmp(((struct Stu*)elem1)->name , ((struct Stu*)elem2)->name);
}
void Swap(char* buf1, char* buf2, int width)
{
	int i = 0;
	for (i = 0; i < width; i++)
	{
		char tmp = *buf1;
		*buf1 = *buf2;
		*buf2 = tmp;
		buf1++;
		buf2++;
	}
}

void bubble_sort(void* base, int num, int width, int(*cmp)(const void* elem1, const void* elem2))
{
	//计算行
	int i = 0;
	for (i = 0; i < num - 1; i++)  //计算冒泡排序的趟数
	{
		//计算列
		int j = 0;
		for (j = 0; j < num - 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);
			}
		}
	}
}


void test2()
{
	struct Stu arr[3] = { {"zhangsan",20,55.5},{"lisi",30,88.0},{"wangwu",10,90.0}};
	int sz = sizeof(arr) / sizeof(arr[0]);
	bubble_sort(arr, sz, sizeof(arr[0]), cmp_stu_by_name);

}

int main()
{
	test2();
	return 0;
}
  • 14
    点赞
  • 37
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值