qsort函数使用样例:对一维数组、指针数组、二维数组进行排序

一、qsort函数

我们知道,包含在函数库stdlib.h中的qsort函数原型如下:
void qsort( void *base, size_t num, size_t wid, int (*cmp)(const void *e1, const void *e2) );
第一个参数base的类型是void*,令它指向待排数组的第一个元素即可。如果待排数组是int类型数组a,那么这里输入a即可。
第二个参数num的类型是size_t(可理解为unsigned int,输入一个int类型的参数可以被隐式类型转换为size_t),输入待排的元素个数即可
第三个参数wid的类型是size_t,记录待排元素的字节数(byte)。比如,如果待排数组是一个int类型数组a,那么这里大概输入4;如果待排数组是定义为int a[3][5]的二维数组a,那么数组的实际元素应该是a[0]、a[1]、a[2],这三个元素均为类型为int[5]的一维数组,那这三个元素的长度应该分别为5*4字节;但是,如果待排数组是定义为int *b[3]的指针数组b,那么数组的实际元素应该是b[0]、b[1]、b[2],这三个元素类型均为int*,即指向int的指针,那这三个元素的长度又应该分别为8(64位系统)。wid参数对排序至关重要,因为传入qsort的参数是void类型指针,它不知道每个元素的长度。当然,如果不关注这些细节,在使用函数时,该参数可以直接由sizeof(a[0])这个式子求得。
第四个参数cmp的类型是int(*)(const void*,const void*),也即一个指向函数的指针,在使用函数时直接输入比较函数名即可。

二、cmp比较函数

下面讨论比较函数,它的原型为int function_name(const void* a,const void* b);
其中const void*类型的形参a、b分别是指向被比较元素的指针!而且它的类型是未定义的,你还需要对它进行强制类型转换,不然编译器会给你报出最为友好的error!
同时,为了防止你在排序时不小心把待排元素的内容改了,造成不可预知的错误,函数的设计者把参数定义为了const void*类型,也就是一个指向类型未定义常量的指针。
这就是说,他从根本上防止了你通过该指针篡改原始数据。至于如何使用该函数,下面我们将提供三个例子来解释。

至于该函数的返回值,是这样设计的,如果你希望第一个参数a所指的元素被排在后面,则return 1;如果你希望第一个参数a所指的元素被排在后面,那么return -1;如果a、b所指的元素相等,那就return 0 。

三、对一个int类型数组进行排序

#include 
#include 
#include 
#define SIZE 100
int cmp(const void* a,const void* b)
{
	int* p1=(int*)a;
	int* p2=(int*)b;
	//将a和b强制类型转换后分别存入int型指针变量p1和p2 
	if (*p1>*p2)
	{
		return 1;
	}
	else if (*p1<*p2)
	{
		return -1;
	}
	else
	{
		return 0;
	}
}
int num[SIZE];
int main(void)
{
	srand(time(0));
	for (int i=0;i

四、对一个指针数组进行排序

1题目信息
cc企业的研发团队目前正在研发 n 款产品。为了平衡成本和性能等因素,研发团队对每款产品计算其若干个性能指标对该产品质量的影响权重。由于数据未经过整理,研发团队无法直观的看出对于某项产品哪些性能指标影响权重较大。现在研发团队把该任务交给你解决。他们提供的数据有:所有产品性能指标总数;对于每个性能指标,一个正整数 id 表示其所属的产品类型,一个自然数 weight 表示其对该产品质量的影响权重大小。请你以产品类型为第一关键字升序,影响权重为第二关键字降序对性能指标进行排序。
2输入格式
共输入 N+1 行。
第一行一个正整数 N ,表示所有性能指标总数。
第 i+1(1≤i≤N) 行,一个正整数 id 和一个自然数 weight ,中间用空格隔开。(意义如题目所示)
3输出格式
共输出 N 行,第 i 行输出按照上述规则排序后的第 i 个指标的排名(从 1 开始)、一个正整数 id 和一个自然数 weight ,行内数与数之间用空格隔开。注:若性能指标的 id 和 weight 完全相同,则排名也相同。

思路:用一个二重int类型指针来存输入的所有主要数据(当然要malloc两下),对这个数组进行排序即可

#include 
#include 

int cmp(const void* x,const void* y)
{
	//待排元素是int*类型的,x指向这些元素,
	//所以x的类型是一个指向int*的指针
	//所以x的类型为int** 
	int **a=(int **)x;
	
	int **b=(int **)y;
	
	if ((*a)[0]>(*b)[0])
	{
		return 1;
	}
	else if((*a)[0]<(*b)[0])
	{
		return -1;
	}
	else
	{
		if ((*a)[1]<(*b)[1])
		{
			return 1;
		}
		else if((*a)[1]>(*b)[1])
		{
			return -1;
		}
		else 
			return 0;
	}
	//这里有特别注意!!!请看下方!!! 
}

int main(void)
{
	int n;
	//用于储存数据组数 
	int **date;
	//用于储存所有数据 
	scanf("%d",&n);
	//读入数据组数到变量n 
	date=(int**)malloc(n*sizeof(int *));
	//为date分配空间,则date[n]是一个指针数组 
	for (int i=0;i=0;k--)
		{
			if (*(*(date+k)+0)!=*(*(date+k+1)+0)||*(*(date+k)+1)!=*(*(date+k+1)+1))
			{
				break;
			}
			else
			{
				num=k;
			}
		}
		//这个循环的目的是找到那些相等的元素,从而对它的序号进行处理 
		
		printf("%d %d %d\n",num+1,*(*(date+i)+0),*(*(date+i)+1));
	}
	
	return 0;
} 

特别注意:在cmp比较函数中,可以看到if和else语句中我写的是(*a)[1]而非*a[1]。这是为什么呢?
这是由于,在c语言中引号[]的优先级比解引用符*高,如果按照后者方式编程,则等价于*(*(a+1))和a[0][1]
而按照标准的写法,则等价于*((*a)+1)和a[0][1],显然,*a[1]是不符合我们的期望的

五、对一个二维数组进行排序
1题目描述
爱吃猪脚的猪脚热衷解谜游戏,他发现解谜游戏里面有一些数字,他觉得将这些数字排好序可能得到一些线索,想拜托你帮忙排好序。
解谜任务卡上写着:请你将数据从小到大排序,并按照顺序编号,相同的数据具有相同的编号。即如果有 n 个相同的数据,它们的编号为 p ,则下一个编号为 n+p 。
输入
2一行若干个实数,每个实数之间使用空格隔开,保证最后一个实数之后没有空格和换行符。
实数可能为小数形式或科学计数法形式,最多保留 6 位小数。
输出
3共 n+1 行输出。
第一行为数据数量 n 。
接下来 n 行,按照输入数据的顺序输出数值,格式为 [编号]: [数值] ,具体见题目描述定义,注意冒号后有一个空格。

思路:

创建ch字符串数组(类型为char[500005][15])用以存储输入信息,创建data二维double型数组(类型为double[500005][3])用以排序。其中data[i][0]用以存储对应浮点数。

如图所示,需要对二维数组进行两次qsort排序

qsort函数使用样例:对一维数组、指针数组、二维数组进行排序_第1张图片

#include 

#include 

char ch[500005][15];

double data[500005][3];

int cmp1(const void* a,const void* b)
{
	double* p1=(double*)a;
	
	double* p2=(double*)b;
	
	if (*p1>*p2)
	{
		return 1;
	}
	else if (*p1<*p2)
	{
		return -1;
	}
	else
	{
		return 0;
	}
}

int cmp2(const void* a,const void* b)
{
	double* p1=(double*)a;
	
	double* p2=(double*)b;
	
	p1++;
	
	p2++;
	//为了让指针指向data[i][1],所以进行++操作! 
	
	if (*p1>*p2)
	{
		return 1;
	}
	else if (*p1<*p2)
	{
		return -1;
	}
	else
	{
		return 0;
	}
}





int main (void)
{
	int max=0;
	
	while (scanf("%s",&ch[max])!=EOF)
	{
		data[max][0]=atof(ch[max]);
		
		data[max][1]=max;
		
		max++;
	}
	
	qsort(data,max,sizeof(data[0]),cmp1);
	
	for (int i=0;i0;k--)
			{
				if (data[k-1][0]!=data[k][0])
				{
					data[i][2]=(double)(k+0.1);
					
					break;
				}
			}
		}
	}
	
	qsort(data,max,sizeof(data[0]),cmp2);
	
	for (int i=0;i

小记:这道题用结构体为最优解

你可能感兴趣的:(c语言,c++,算法,学习)