[C language] The secret of qsort

1. The goal of this article 

The qsort function can sort any type of data, even the data inside the structure, according to the rules you want. It is very powerful, but why?

I will simulate and implement the qsort function to give you a clear and profound understanding of the entire process.


2. qsort function prototype

void qsort (void* base,//要排序的对象的第一个元素的首地址
            size_t num, //对象的个数
            size_t size,//每一个对象的大小 Size in bytes
            int (*compar)(const void*,const void*));//Pointer to a function that compares two elements.(并且这个函数要自己写)

        The bottom layer of the qsort function is performed through quick sort, but this is not what we are interested in. I want to know why qsort can sort any type of data. It has nothing to do with the sorting algorithm it uses. Therefore, we use a relatively simple risk Bubble sort replaces the quick sort algorithm and gives bubble sort the powerful function of sorting any type of data.


3. Bubble sorting - large numbers sink to the bottom and small numbers float

 For bubble sorting, the basic idea is that large numbers sink to the bottom and small numbers float;

The source code is given directly here:

void Bubble_sort(int arr[], int size)
{
	int j,i;
	for (i = 0; i < size-1;i++)//排序趟数等于元素个数-1
	{
		int f = 0;
		for (j = 0; j < size - 1 - i; j++)//每一趟都有一个元素复位,需要排序的次数每次-1
		{
			if ( arr[j] > arr[j+1] )
			{
                int tem = arr[j];
				arr[j] = arr[j+1];
				arr[j+1] = tem;
				f = 1;
			}
		}
		if (f == 0)	
		{
            break;
        }
	}

3.1 Compared with qsort, the limitations of bubble sort

        Only integer data can be sorted 

Four, two questions:

4.1 Indefinite type comparison problem

        ​ ​ 1. For the internal judgment of if, although character types can be compared using >,<,=, string types cannot be compared by conventional methods;

4.2 Indefinite type exchange problem

        ​ ​ 2. For the exchange part, since different elements have different types and occupy different memory spaces, how to determine the type of incoming data and realize the exchange of the two data?


5. Transform bubble sorting

We call the qsort function we simulate and implement my_qsort, and the implementation is as follows:


void my_qsort(void* base,size_t sz,size_t width,int (*cmp)(const void* p1,const void* p2))//cmp 是函数指针,在my_sort中被多次调用
{//它指向的函数是int_cmp,int_cmp就是回调函数
	int i = 0;
	for(i = 0;i < sz - 1;i++)//趟数不变
	{
		int j = 0;
		for(j = 0;j < sz - i - 1;j++)//每一趟进行的比较数不变
		{
			if(cmp((char*)base + j * width,(char*)base + (j + 1) * width) > 0 )//判断要改变
			{
				Swap((char*)base + j * width,(char*)base + (j + 1) * width,width);
			}
		}
	}
}

5.1 Comparison of different types

We define a cmp function to implement comparison:

5.1.1cmp actual parameters

We pass in the address of the first element of the sorted array, base, and force the base type into the char* type, so that the operation between base and integer will only span this integer number of bytes;

If we know the size (length) of each element, then we can accurately access each element;


How to understand it?​ 

 e.g.1: For int

 The position of the base pointer in the picture is j == 1

 e.g.2: For char

 

 The position of the base pointer in the picture is the position of j == 5 

5.1.2cmp type reference

int int_cmp(const void* p1,const void* p2)
{
	return *(int*)p1 - *(int*)p2;
}

Since the comparison object is an integer, a function is defined to compare integers. The void* type cannot be directly dereferenced, so p1 and p2 are forced to type conversion, and the two numbers are subtracted and returned.

5.2 Indefinite type exchange problem

Define the exchange function Swap 

void Swap(char* buf1,char* buf2,int width)//按字节逐个交换
{
	for(int i = 0;i < width;i++)
	{
		char tem = *buf1;
		*buf1 = *buf2;
		*buf2 = tem;
		buf1++;//如果是整型,则要遍历四个字节
		buf2++;
	}
}

At this time, we know the meaning of defining width. For a data type, although we don't know its type, we can exchange data byte by byte according to its length.


Overall code execution

For all types, our bubble sort can be sorted. Its function is consistent with the library function qsort. We still need to write the cmp function ourselves:;

Sorting of int type data:

#include<stdio.h>
#include<string.h>
int int_cmp(const void* p1,const void* p2)
{
	return *(int*)p1 - *(int*)p2;
}
void Swap(char* buf1,char* buf2,int width)//按字节逐个交换
{
	for(int i = 0;i < width;i++)
	{
		char tem = *buf1;
		*buf1 = *buf2;
		*buf2 = tem;
		buf1++;//如果是整型,则要遍历四个字节
		buf2++;
	}
}

void my_qsort(void* base,size_t sz,size_t width,int (*cmp)(const void* p1,const void* p2))//cmp 是函数指针,在my_sort中被多次调用
{//它指向的函数是int_cmp,int_cmp就是回调函数
	int i = 0;
	for(i = 0;i < sz - 1;i++)//趟数不变
	{
		int j = 0;
		for(j = 0;j < sz - i - 1;j++)//每一趟进行的比较数不变
		{
			if(cmp((char*)base + j * width,(char*)base + (j + 1) * width) > 0 )//判断要改变
			{
				Swap((char*)base + j * width,(char*)base + (j + 1) * width,width);
			}
		}
	}
}

void test1(void)
{
	int arr[] = {2,5,8,9,6,3,1,4,7,0};
	int sz = sizeof(arr)/sizeof(arr[0]);
	my_qsort(arr,sz,sizeof(arr[0]),int_cmp);
	
	for(int i = 0;i < sz;i++)
	{
		printf("%d ",arr[i]);
	}
}

int main()
{
    test1();
    return 0;
}

For structure types, you can also sort based on the characteristics of an element inside the structure:

Structure type

Sort the int type data in the structure:


struct stu
{
	char name[20];
	int age;
};

int struct_cmp_by_age(const void* p1,const void* p2)
{
	return ((struct stu*)p1)->age - ((struct stu*)p2)->age;
}

void test2(void)
{
	struct stu arr[] = {
   
   {"zhangsan",18},{"lisi",25},{"wangwu",30},{"xiaoming",40}};
	int sz = sizeof(arr)/sizeof(arr[0]);
	my_qsort(arr,sz,sizeof(arr[0]),struct_cmp_by_age);
	for(int i = 0;i < sz;i++)
	{
		printf("%s %d\n",arr[i].name,arr[i].age);
	}
}

int main()
{
    test2();
    return 0;
}

Sort the char type data in the structure:


struct stu
{
	char name[20];
	int age;
};

int struct_cmp_by_name(const void* p1,const void* p2)
{
	return strcmp(((struct stu*)p1)->name,((struct stu*)p2)->name);
}

void test3(void)
{
	struct stu arr[] = {
   
   {"zhangsan",18},{"lisi",25},{"wangwu",30},{"xiaoming",40}};
	int sz = sizeof(arr)/sizeof(arr[0]);
	my_qsort(arr,sz,sizeof(arr[0]),struct_cmp_by_name);
	for(int i = 0;i < sz;i++)
	{
		printf("%s %d\n",arr[i].name,arr[i].age);
	}
}


int main()
{
	
	//test1();
	//test2();
	test3();
	return 0;
}


1. The strcmp function in <string.h> is used to compare strings, and its return value exactly meets the fourth parameter of the qsort function: the requirements of the function. 

 

 

The first string is greater than the second one, and strcmp returns a number greater than 0. The corresponding qsort function requires the return value of the fourth function to be greater than 0, which means that the first parameter is larger than the second one.​ 


Review of this article 

Table of contents

1. The goal of this article 

2. qsort function prototype

3. Bubble sorting - large numbers sink to the bottom and small numbers float

3.1 Compared with qsort, the limitations of bubble sort

Four, two questions:

4.1 Indefinite type comparison problem

4.2 Indefinite type exchange problem

5. Transform bubble sorting

5.1 Comparison of different types

5.1.1cmp actual parameters

5.1.2cmp type reference

5.2 Indefinite type exchange problem

Overall code execution

Sorting of int type data:

Structure type

Sort the int type data in the structure:

Sort the char type data in the structure:


Finished~

Reprinting without the author's consent is prohibited

Guess you like

Origin blog.csdn.net/2301_79465388/article/details/134587878