C语言:qsort详解 并实现--整形 浮点数 字符 字符串 结构体排序

一.qsort函数详解

1.1 简介

  • qsort是C语言库函数中的一个排序函数,底层逻辑是快速排序(quick sort)
  • 头文件<stdlib.h>
  • 功能:排序任意类型的数组元素

1.2 函数声明及参数详解

void qsort(void* base, //指向待排序数组的第一个元素的指针
		   size_t num, //base指向数组中的元素个数
		   size_t size,//base指向的数组中一个元素的大小  单位是字节
		   int (*compar)(const void*, const void*)
		   //compar是函数指针,指向一个比较两个元素的函数(回调函数)
		   )

1.3 回调函数

回调函数:一个通过函数指针调用的函数
如果把函数的指针(地址)作为参数传递给另⼀个函数,当这个指针被⽤来调⽤其所指向的函数时,被调⽤的函数就是回调函数。回调函数不是由该函数的实现⽅直接调⽤,⽽是在特定的事件或条件发⽣时由另外的⼀⽅调⽤的,⽤于对该事件或条件进⾏响应

1.4 compar参数

函数原型: int compar(const void*p1, const void*p2)

  • compar参数是函数指针,指向一个比较两个元素的函数,这个函数是自定义的,根据用户想比较的数据类型进行变换,这里称它所指向的函数也为compar。
  • 注意:
    两个形参必须得是const void*类型,再在自定义的比较函数内部将const void*强制转换为需要的类型(void*类型的指针可以接收任意类型的地址,但不能对其解引用和加减整数)
  • 返回值:
    如果compar返回值小于0(< 0),那么p1所指向元素会被排在p2所指向元素的左面;
    如果compar返回值等于0(= 0),那么p1所指向元素与p2所指向元素的顺序不确定;
    如果compar返回值大于0(> 0),那么p1所指向元素会被排在p2所指向元素的右面。
    因此可直接通过获取p1与p2指向的数据作差(即分别强转>>解引用>>作差)即可
    通过这些可以观察到qsort默认升序,若想获得降序只需p1和p2更换位置即可

以整型数组为例:

int cmp_int(const void*a, const void*b)
{
	//return *(int*)a - *(int*)b;//升序
	return *(int*)b - *(int*)a;//降序
}

二.整型排序

代码如下:

#include <stdio.h>
#include <stdlib.h>

void Print1(int* arr, int sz)
{
	for (int i = 0; i < sz; i++)
	{
		printf("%d ", *(arr + i));
	}
	printf("\n");
}
int cmp_int(const void*a, const void*b)
{
	//return *(int*)a - *(int*)b;//升序
	return *(int*)b - *(int*)a;//降序
}
void test1()
{
	int arr[] = { 3,1,5,11,2,0,13,7,9,21,17 };
	int sz = sizeof(arr) / sizeof(arr[0]);
	Print1(arr, sz);
	qsort(arr, sz, sizeof(arr[0]), cmp_int);
	Print1(arr, sz);
}
int main()
{
	test1();
	return 0;
}

三.浮点数排序

代码如下:

#include <stdio.h>
#include <stdlib.h>

void Print2(float* arr, int sz)
{
	for (int i = 0; i < sz; i++)
	{
		printf("%f ", *(arr + i));
	}
	printf("\n");
}
int cmp_float(const void* a, const void* b)
{
	//return *(float*)a - *(float*)b;//升序
	return *(float*)b - *(float*)a;//降序
}
void test2()
{
	float arr[5] = { 0 };
	printf("请输入你想排序的5个浮点数:");
	int sz = sizeof(arr) / sizeof(arr[0]);
	for (int i = 0; i < sz; i++)
	{
		scanf("%f", &arr[i]);
		//注意这里的占位符是%f 且后面不能有空格 不然输入的时候会出现问题
	}
	qsort(arr, sz, sizeof(arr[0]), cmp_float);
	Print2(arr, sz);
}
int main()
{
	test2();
	return 0;
}

在这里插入图片描述

四.字符排序

注意: 使用scnaf输入字符时应使用%c,但要注意%c不会忽略空白字符,总是返回当前第一个字符,无论该字符是否为空格,所以注意输入多个字符时,中间别包含空格,不然%c会把空格也读上,如果要强制跳过字符前的空白字符,可以写成在%c前加一个空格

代码如下:

#include <stdio.h>
#include <stdlib.h>

void Print3(char* arr, int sz)
{
	for (int i = 0; i < sz; i++)
	{
		printf("%c ", *(arr + i));
	}
	printf("\n");
}
int cmp_char(const void* a, const void* b)
{
	//return *(char*)a - *(char*)b;//升序
	return *(char*)b - *(char*)a;//降序
}
void test3()
{
	char arr[5] = { 0 };
	printf("请输入你想排序的5个字符:");
	int sz = sizeof(arr) / sizeof(arr[0]);
	for (int i = 0; i < sz; i++)//i是什么类型没有太大影响 它只影响循环次数
	{
		scanf("%c", arr+i);//不会忽略空格 输入abcde 才会正常打印e d c b a
		//scanf(" %c", arr+i);//写成这样会强制跳过空格 输入a b c d e 会正常打印e d c b a
	}
	qsort(arr, sz, sizeof(arr[0]), cmp_char);
	Print3(arr, sz);
}
int main()
{
	test3();
	return 0;
}

五.字符串排序

  • 两个字符串比较相等时,不是使用==,而是使用库函数strcmp,头文件<string.h>
    函数原型:int strcmp(const char*s1, const char*s2)
    返回值:当s1<s2时,返回负数; 当s1=s2时,返回0; 当s1>s2时,返回正数;
    正好与比较函数的返回值匹配

代码如下:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

void Print5(char* arr[], int sz)
{
	for (int i = 0; i < sz; i++)
	{
		printf("%s ", arr[i]);
	}
	printf("\n");
}
int cmp_char(const void* p1, const void* p2)
{
	return strcmp((char*)p1, (char*)p2);
}
void test5()
{
	char* arr[5] = { "aaaaa", "aaaab", "aaabb", "aabbb", "abbbb" };
	int sz = sizeof(arr) / sizeof(arr[0]);
	qsort(arr, sz, sizeof(arr[0]), cmp_char);
	Print5(arr, sz);
}
int main()
{
	test5();
	return 0;
}

在这里插入图片描述

六.结构体排序

  • 结构体有许多成员,可根据不同成员进行排序
  • 注意: 要么结构体定义在最前面,要么就前面放上结构体声明,不然后续使用结构体时会报错

代码如下:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

struct Student
{
	char name[20];
	int age;
	float score;
};
void Print(struct Student* arr, int sz, char* x)
{
	printf("根据%s排序:", x);
	if (strcmp(x, "name") == 0)
	{
		for (int i = 0; i < sz; i++)
		{
			printf("{%s,%d,%f}  ", arr[i].name,arr[i].age, arr[i].score);
		}
		printf("\n");
	}
	else if (strcmp(x, "age") == 0)
	{
		for (int i = 0; i < sz; i++)
		{
			printf("{%s,%d,%f}  ", arr[i].name, arr[i].age, arr[i].score);
		}
		printf("\n");
	}
	else
	{
		for (int i = 0; i < sz; i++)
		{
			printf("{%s,%d,%f}  ", arr[i].name, arr[i].age, arr[i].score);
		}
		printf("\n");
	}		
}
//strcmp函数原形:int strcmp(const char*string1, const char*string2)
//注意括号里参数是指针变量
int cmp_struct_name(const void* a, const void* b)
{
	//return strcmp(((struct Student*)a)->name, ((struct Student*)b)->name);//升序
	return strcmp(((struct Student*)b)->name, ((struct Student*)a)->name);//降序
	//结构体间接访问操作符:结构体指针->成员名
	//结构体直接访问操作符:结构体名.成员名
}
int cmp_struct_age(const void* a, const void* b)
{
	//return ((struct Student*)a)->age - ((struct Student*)b)->age;//升序
	return ((struct Student*)b)->age - ((struct Student*)a)->age;//降序
}
int cmp_struct_score(const void* a, const void* b)
{
	//return ((struct Student*)a)->score - ((struct Student*)b)->score;//升序
	return ((struct Student*)b)->score - ((struct Student*)a)->score;//降序
}
void test4()
{
	struct Student arr[] = {{"Bob", 20, 86.3},{"Mary", 19, 54.1},{"Lucy",18, 95.2}};
	int sz = sizeof(arr) / sizeof(arr[0]);
	qsort(arr, sz, sizeof(arr[0]), cmp_struct_name);
	Print(arr, sz, "name");
	qsort(arr, sz, sizeof(arr[0]), cmp_struct_age);
	Print(arr, sz, "age");
	qsort(arr, sz, sizeof(arr[0]), cmp_struct_score);
	Print(arr, sz, "score");
}
int main()
{
	test4();
	return 0;
}

在这里插入图片描述
创作不易,希望大家多多支持,有什么观点欢迎讨论🌹🌹

  • 29
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值