qsort函数的使用及其实现

文章目录

  • 一、qsort函数是什么?
  • 二、参数介绍及代码实例
  • 三、qsort函数的实现

一、qsort函数是什么?

qsort函数是C语言中的一个函数库函数,可以用来对不同类型的数组进行排序。

二、参数介绍及代码实例

qsort函数有4个参数,分别是
1.被排序数组的数组名(首元素的地址)
2.数组中元素的个数(sizeof(arr)/sizeof(arr[0]))
3.数组中元素所占据的字节数,例如对一个float型数组,所占据的字节数就是sizeof(float)=4
4.第四个参数是一个函数指针,这个参数是特别重要的,这个函数指针的意义是告诉qsort函数我们的比较方式
代码如下(示例):

#include
#include
#include
typedef struct Stu
{/*结构体中的字符数组项不能省略长度*/
	int age;
	char names[20];
}Student;
int Cmpint(const void* p1, const void* p2)
{
	/*这个函数的作用是比较2个元素的大小
		用p1来接受第一个元素的地址,p2来接收第二个元素的地址
		这里假设p1接收的是& arr[0],p2接收的是& arr[1]
		如果* (int*)p1 > * (int*)p2, 就返回一个大于0的值
		如果* (int*)p1 = *(int*)p2, 就返回一个等于0的值
		如果* (int*)p1 < *(int*)p2, 就返回一个小于0的值*/
		return *(int*)p1- *(int*)p2;
}
int Cmpfloat(const void* p1, const void* p2)
{
	return (int)(*(float*)p1 - *(float*)p2);
}
int Cmpstructage(const void* p1, const void* p2)
{
	return ((struct Stu*)p1)->age - ((struct Stu*)p2)->age;
}
int Cmpstructname(const void* p1, const void* p2)
{/*p1指向的值大于p2指向的值就返回正数,并且从小到大进行排序*/
	return strcmp(((Student*)p1)->names,((Student*)p2)->names);
}
void test1()
{
	int arr[] = { 1,3,5,6,9,6,63,6,52 };
	int i = 0;
	int sz = sizeof(arr) / sizeof(arr[0]);
	qsort(arr, sz, sizeof(arr[1]), Cmpint);
	for (i = 0; i < sz; i++)
	{
		printf("%d ", arr[i]);
	}

}
void test2()
{
	float b[] = {1.2,2.3,5.6,9.6,5.34,6.259,3.693 };
	int i = 0;
	qsort(b, sizeof(b) / sizeof(b[1]), sizeof(float), Cmpfloat);
	for ( i = 0; i < sizeof(b) / sizeof(b[1]); i++)
	{
		printf("%f ", b[i]);
	}
}
void test3()
{/*根据年龄排序*/
	int i = 0;
	struct Stu s[3] = { {25,"zhangsan"},{20,"lis"},{30,"wangwu"} };
	qsort(s, sizeof(s) / sizeof(s[1]), sizeof(s[0]), Cmpstructage);
	for ( i = 0; i < sizeof(s) / sizeof(s[1]); i++)
	{
		printf("%s ", s[i].names);
		printf("%d\n", s[i].age);
	}
}
void test4()
{
	struct Stu student[3] = { {15,"zhang"},{13,"li"},{42,"buu"} };
	qsort(student, sizeof(student) / sizeof(student[1]), sizeof(student[0]), Cmpstructname);
};
int main()
{
	/*test1();*/
	/*test2();*/
	/*test3();*/
	test4();
}

这里比较难以理解的就是第四个参数函数指针,下面的代码将简要说明该函数指针的意义

三、qsort函数的实现

#define _CRT_SECURE_NO_WARNINGS
#include
#include
struct Stu
{
	char names[20];
	int age;
};
int cmpstruct_age(const void* m1, const void* m2)
{
	return ((struct Stu*)m1)->age - ((struct Stu*)m2)->age;
}
int cmpstruct_name(const void* m1, const void* m2)
{
	return strcmp(((struct Stu*)m1)->names, ((struct Stu*)m2)->names);
}
void swap(char* t1, char* t2, int width)
{
	/*每一个元素大小是width个字节,char* 解引用指针访问一个字节
		t1是首元素的开始地址,t2是下面一个元素的开始地址*/
	int i = 0;
	for (i = 0; i < width; i++)
	{
		char tmp = *(t1 + i);
		*(t1 + i) = *(t2 + i);
		*(t2 + i) = tmp;
	}

}
int cmpint(const void* m1/*前面元素的起始位置*/, const void* m2/*下一个元素的起始位置*/)
{
	return *((int*)m1) - *((int*)m2);
}
int cmpchar(const void* m1, const void* m2)
{
	if (*(char*)m1> *(char*)m2)
	{
		return 1;
	}
	else
	{
		return 0;
	}
}
void myqsort(void* dest/*首元素地址*/,int sz/*元素个数*/,int width,int(*cmp)(const void*,const void*))
{
	/*      (char*)dest + i*width是下标为i的元素的地址
		    |****|****         */
		int i = 0;
		for ( i = 0; i < sz; i++)/*  sz个元素排序,下标为0~sz-1  */
		{/*i=0,sz-1次比较。i=1,sz-2次比较*/
			int j = 0;
			for ( j = 0; j <sz-i-1; j++)
			{
				if (cmp((char*)dest + j * width, (char*)dest + (j +1)*width)>0)
				{/*表示前面一个元素大于后面一个元素*/
					swap((char*)dest + j * width, (char*)dest + (j + 1)*width,width);
				}/*swap函数实现交换*/
			}
		}
}
int main()
{
	/*int arr[10] = { 2,3,5,6,4,7,8,9,10,1 };
	myqsort(arr, sizeof(arr) / sizeof(arr[0]), sizeof(arr[0]),cmpint);*/
	/*char arr[] = "asdfertgh";
	myqsort(arr, strlen(arr), sizeof(arr[0]), cmpchar);*/
	struct Stu s[4] = { {"zhangsan",10},{"lisi",8},{"wangwu",12},{"tom",9} };
	myqsort(s, sizeof(s) / sizeof(s[0]), sizeof(s[0]), cmpstruct_name);
	return 0;
}

qsort函数设计的巧妙之处在于它用void的指针来接受任意类型的数组的首元素地址,然后将其转化为char类型的指针,由于char*的指针进行解引用一次访问一个字节,配合第三个参数(数组中每个元素所占据的字节数)就可以实现一个字节一个字节的对数组中的内容进行更改,而不用去关心数组中的元素到底是什么类型。

你可能感兴趣的:(c语言,c++,数据结构)