用C语言简单模拟实现qsort

在学习使用函数qsort之前,先熟悉一下简单的冒泡排序。

int arr[10]={10,9,8,7,6,5,4,3,2,1}; 假设要使该数组中的内容由由小到大依次排序。

思路:

  从第下标为0的第一个元素开始,与下一个元素进行比较,若该元素大于下一个元素,则交换,接着依次进行,第一个元素一直要比较到最后一个,一共有10个元素,所以需要10轮,在第一个元素进行比较时,需要比较10次,而第二个元素只需要比较8次即可,因为在第一轮循环中,已经把最大的元素交换到数组最后。所以需要两个for循环嵌套。

用C语言简单模拟实现qsort_第1张图片

具体代码如下:

void Bubble_sort(int arr[], int sz)
{
	int i = 0;
	for (i = 0; i < sz - 1; i++)
	{
		int j = 0;
		for (j = 0; j < sz - 1 - i; j++)
		{
			if (arr[j] < arr[j + 1])
			{
				int temp = arr[j];
				arr[j] = arr[j + 1];
				arr[j + 1] = temp;
			}
		}
	}
}


qsort函数是C语言的库函数之一,基于快速排序算法实现的一个库函数。在库stdlib.h中,在使用时要包含该库的头文件。

下面是qsort的部分说明:

用C语言简单模拟实现qsort_第2张图片

void qsort(void *base ,size_t num,size_t width, int (*cmp)(const void*e1 ,const void*e2);

该函数没有返回值。

void* base 待排序位置的起始地址

num 是排序的个数

width 是排序元素的字节大小

int(*cmp)(const void*e1,const void*e2)  是一个函数指针,cmp为比较函数  e1 e2 待比较两个元素的地址,如果e1>e2,则返回一个>0的数,如果e1=e2则返回0,如果e1

用C语言简单模拟实现qsort_第3张图片

 1、qsort的用法

1、qsort实现冒泡排序

#include 
#include 
void print(int* arr, int sz)
{
	int i = 0;
	for (i = 0; i <=sz - 1; i++)
	{
		printf("%d ", *(arr + i));
	}
}
int cmp(const void* e1, const void* e2)
{
	return *(int*)e1 - *(int*)e2;  // 默认为升序
}
int main()
{
	int arr1[10] = { 9,8,7,6,5,4,3,2,1,0 };
	int sz = sizeof(arr1) / sizeof(arr1[0]);
	qsort(arr1, sz, sizeof(arr1[0]), cmp);
	print(arr1, sz);
}

qsort的功能是非常强大的,这个int 类型是比较简单普遍的类型,也可以交换各种类型,如结构体类型。举例说明:

1、使结构体的内容按年龄排序。

//定义一个结构体
struct Stu
{
	char name[20];
	int age;
	int score;
};
int cpm_age(const void* e1, const void* e2)  // 比较年龄就写一个结构体年龄类型的比较
{
	return ((struct Stu*)e1)->age - ((struct Stu*)e2)->age;
}
int main()
{
	struct Stu  arr[3] = { {"zhangsan",20,55} ,{"lisi",25,56}, {"wangma",19,60}};
	int sz = sizeof(arr) / sizeof(arr[0]);
	qsort(arr, sz, sizeof(arr[0]), cpm_age);
}

注意:

  void* 这个类型的指针是万能的,兼容全部类型的指针,但是在用到该函数时,要将比较的元素强制类型转换为需要的类型,如比较整型就强制类型转换为整型,如果比较结构体类型,就强制类型转换为结构体类型。

2、使结构体的内容按名称排序。

不需要太大的改动,因为两个字符串之间是不能直接比较大小的,要用库函数中的strcmp函数比较。

strcmp函数是字符串比较函数,首先比较两个字符串的第一个字符,若这两个字符相等,则会继续比较下一个。

 

用C语言简单模拟实现qsort_第4张图片


自己写一个函数,模拟实现qsort。

//用冒泡排序模拟实现qsort;
void Bubble_sort(void* base, int num, int width,int (*cmp)(const void* e1, const void* e2))
{
	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);
			}
		}
	}
}

  在比较函数 cmp( (char*)base+j*width, (char*)base+(j+1)*width)中,里面的两个参数需要强制类型转换,因为void* 是空类型指针,没有实际意义,不能直接使用所以需要强制类型转换。在强制类型转换时,如果单一的强制类型转换为(int*)时,只能交换整型数据,兼容性很差。参考qsort函数,字符型、整型、自定义类型都可兼容。一个字符型指针变量能访问一个字节,一个短整型变量能访问两个字节,一个整型变量能访问4个字节。所以把数据强制类型转换为字节最小的,然后在累加,就可以达到类型所正常访问的字节。

用C语言简单模拟实现qsort_第5张图片

 如果base是一个整型,则base+1跳过四个字节,到下一个元素,但是base强制类型转换成char*类型的时候,base+1只能访问一个字节,要想访问整型的四个字节,只需base+1*width即可。

void swap(char* buf1,char* buf2,int width)  //必须要知道元素的字节,如果是字符型,交换一个,如果是整型,则交换四个字节
{
	int i = 0;
	for (i = 0; i < width; i++)
	{
		char temp = *buf1;
		*buf1 = *buf2;
		*buf2 = temp;
		buf1++;
		buf2++;
	}
}

在交换数据的时候,一个整型占四个字节,所以需要交换四个字节。

用C语言简单模拟实现qsort_第6张图片

 在写cap函数时,因为所需的变量是整型,所以只需将两个比较的类型强制转换为 (int*)即可

 

int cap_init(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++)
	{
		char temp = *buf1;
		*buf1 = *buf2;
		*buf2 = temp;
		buf1++;
		buf2++;
	}
}
//用冒泡排序模拟实现qsort;
void Bubble_sort(void* base, int num, int width,int (*cmp)(const void* e1, const void* e2))
{
	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);
			}
		}
	}
}
int cap_init(const void* e1, const void* e2)
{
	return* (int*)e1 - * (int*)e2;
}
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, 4, cap_init);
	print(arr, sz);
	return 0;
}

你可能感兴趣的:(c语言,c++,开发语言)