Simulation implementation of qsort function in c language

Preliminary knowledge about qsort function

Callback

A callback function is a function called through a function pointer.
if youTake the pointer (address) of the function as a parameterPassed to another function, when this pointer is used to call the function it points to, the called function is the callback function. The callback function is not called directly by the implementer of the function, but is called by another party when a specific event or condition occurs to respond to the event or condition.
It may be a bit abstract to talk about it this way, and I will introduce it in detail when I talk about actual cases below:>

Function pointer type analysis

When we hear the name function pointer, we will definitely think that this must be a pointer! In fact, otherwise, pointers are used to store addresses, so the function pointer variable should be used to store the function address, and the function can be called through the address in the future.
So how do you get the address of a function? Let's write a piece of code:
Insert image description here
Through debugging, it is not difficult to see that functions have addresses. The function name is the address of the function. Of course, the address of the function can also be &obtained through the function name. So how to receive the address of the function? At this time, the function pointer is introduced. Let’s take Addthe function as an example:
Insert image description here

qsort function usage and related parameters

Let’s take a look at the explanation given by cplusplus.com
Insert image description here
Insert image description here
! (1) The first parameter is the address of the first element to be sorted (here baseit points to the address). Because the type of the element is not known, it is void*used Variable name;
(2) The second parameter is the number of elements to be sorted;
(3) The third parameter is the size of each element to be sorted;
(4) The third parameter is a function pointer pointing to comparThe function can compare two elements. This function needs to be implemented by ourselves;
we can observe that comparthe function return type is intand the parameter type is const void*. have to be aware of isParameters of type void*cannot be directly compared in size, and type conversion must be performed before comparison! ! !

bubble sort algorithm

Let’s look at the original bubble sort algorithm:

void bubble_sort(int arr[], int sz)
{
    
    
	int i = 0;
	for (i = 0; i < sz; i++)
	{
    
    
		int flag = 1;
		for (int j = 0; j < sz - 1 - i; j++)
		{
    
    
			if (arr[j] > arr[j + 1])
			{
    
    
				int tmp = arr[j];
				arr[j] = arr[j + 1];
				arr[j + 1] = tmp;
				flag = 0;
			}
		}
		if (flag == 1)
			break;
	}
}
int main()
{
    
    
	int arr[] = {
    
     1,5,3,6,8,8,5,9,6,5 };
	int len = sizeof(arr) / sizeof(arr[0]);
	bubble_sort(arr, len);
	for (int i = 0; i < len; i++)
	{
    
    
		printf("%d ", arr[i]);
	}
	putchar('\n');
	return 0;
}

Illustration:
Insert image description here
Through the above illustration, as long as we know how many times we need to loop, there is actually nothing difficult. We can use two levels forof loops to implement bubble sort. Remember outer lenlevel , inner len-ilevel circulation.

Introduction to simulation implementation methods

So now that we understand the bubble sort algorithm, how can we improve it into a similar qsortfunction?
In fact, it is still a two-layer loop, the outer layer lenand the memory len-ilayer. What has changed is the comparison function cmp((char*)base + j * width, (char*)base + (j + 1) * width);
because it is difficult to directly exchange the elements to be sorted, an exchange function is used here Swap((char*)base + j * width, (char*)base + (j + 1) * width, width);;
the functions in these two functions basehave been converted to char*, why? Because we don't know the specific element type, in order to facilitate traversal, we will void*convert it to char*a type. At this time, someone will definitely ask, why not transform into int*, short*etc. type?
The answer lies in the size of the elements to be sorted. If each element to be sorted is a structure and each occupies 9 bytes, then the 4 bytes and int2 bytes shortcannot be divisible, resulting in incomplete exchange! It is also to enable Swapthe function to pass the first byte address of the element to be compared every time, and to skip one element every time j*widththrough the sum.(j+1)*width

void Swap(char* buf1, char* buf2, size_t width)
{
    
    
	for (int i = 0; i < width; i++)
	{
    
    
		char tmp = *buf1;
		*buf1 = *buf2;
		*buf2 = tmp;
		buf1++; buf2++;
	}
}

SwapTherefore, each time a byte is exchanged in this function, widthone element is exchanged, which forcan be achieved with a loop.

source code

struct Stu
{
    
    
	char name[20];
	int age;
};
//比较数组元素
int cmp_int(const void* e1, const void* e2)
{
    
    
	return *(int*)e1 - *(int*)e2;
}
//比较结构体中的年龄
int cmp_str_by_age(const void* e1, const void* e2)
{
    
    
	return ((struct Stu*)e1)->age - ((struct Stu*)e2)->age;
}
//比较结构体中的字符串
int cmp_str_by_name(const void* e1, const void* e2)
{
    
    
	return strcmp(((struct Stu*)e1)->name, ((struct Stu*)e2)->name);
}
//交换两个元素(因为不知道元素类型,所以以一字节为单位逐个交换,至width大小)
void Swap(char* buf1, char* buf2, size_t width)
{
    
    
	for (int i = 0; i < width; i++)
	{
    
    
		char tmp = *buf1;
		*buf1 = *buf2;
		*buf2 = tmp;
		buf1++; buf2++;
	}
}
//其中调用函数指针,指向cmp函数
void bubble_sort(void* base, size_t sz, size_t width, int (*cmp)(const void* e1, const void* e2))
{
    
    
	int i = 0;
	for (i = 0; i < sz; i++)
	{
    
    
		int flag = 1;//测试是否已排序完成,提高效率
		for (int j = 0; j < sz - 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);
				flag = 0;
			}
		}
		if (flag == 1)
			break;
	}
}
//整形数组
void test1()
{
    
    
	int arr1[] = {
    
     1,5,3,6,4,9,2,9,6,5 };
	int len = sizeof(arr1) / sizeof(arr1[0]);
	bubble_sort(arr1, len, sizeof(arr1[0]), cmp_int);
	for (int i = 0; i < len; i++)
	{
    
    
		printf("%d ", arr1[i]);
	}
	putchar('\n');
}
//结构体数组--比较age,整形
void test2()
{
    
    
	struct Stu arr2[] = {
    
     {
    
    "zhangsan",16},{
    
    "lisi",37},{
    
    "wangwu",22} };
	int len = sizeof(arr2) / sizeof(arr2[0]);
	bubble_sort(arr2, len, sizeof(arr2[0]), cmp_str_by_age);
}
//结构体数组--比较name,字符串
void test3()
{
    
    
	struct Stu arr3[] = {
    
     {
    
    "zhangsan",16},{
    
    "lisi",37},{
    
    "wangwu",22} };
	int len = sizeof(arr3) / sizeof(arr3[0]);
	bubble_sort(arr3, len, sizeof(arr3[0]), cmp_str_by_name);
	struct Stu* prv = arr3;
	for (int i = 0; i < len; i++)
	{
    
    
		printf("%s  ", prv->name);
		prv++;
	}
}
int main()
{
    
    
//三个测试函数
	test1();
	//test2();
	test3();
	
	return 0;
}

Insert image description here

Guess you like

Origin blog.csdn.net/2301_77404033/article/details/132368136