Analysis of C language library functions -- qsort function (quick sort)

Posted by member123 on Fri, 17 Dec 2021 06:40:15 +0100

Article catalog

  • preface
  • I Bubble sorting
  • II Limitations of bubble sorting
  • 3, Use and advantages of qsort function
  • 4, Implementation of qsort function by bubble sorting simulation
  • summary

preface

Sorting is often used in our daily programming, and bubble sorting is also our most common sorting method. Here we analyze bubble sorting and introduce the qsort function of quick sorting of our protagonist - > C language library function

1, Bubble sorting

First, we introduce the bubble sorting Code:

#include <stdio.h>
int main()
{
	int arr[10] = { 3,4,2,7,8,9,6,0,1,5 };
	int i = 0;
	int j = 0;
	int sz = sizeof(arr) / sizeof(arr[0]);
	for (j = 1; j < sz; j++)
	{
		for (i = 0; i < sz - j; i++)
		{
			if (arr[i] > arr[i + 1])
			{
				int temp = arr[i];
				arr[i] = arr[i + 1];
				arr[i + 1] = temp;
			}
		}
	}
	for (i = 0; i < sz; i++)
	{
		printf("%d ", arr[i]);
	}
	return 0;
}

Several important code parsing:

1. Calculate the number of array elements

 2. Number of bubble sort cycles

In our current code, the value of sz is 10, so if 9 numbers are sorted well, the remaining number must be sorted well, so we can know that the number of times of bubble sorting is 1 less than the number of elements

3. Number of elements in bubble sort

In our current code, the value of sz is 10. Each bubble sort can sort a number, so the number of elements in the next cycle should be - 1. Remove the sorted number and sort the remaining elements for the next bubble sort

4. Comparative judgment

In the above code, we arrange the array elements in ascending order, so we can judge whether the front element is smaller than the rear element. If so, enter the if statement for element exchange

2, Limitations of bubble sorting

As shown in the code above, the code for comparing element sizes

The code we wrote in the above figure is limited to comparing integer elements. If we change the integer arr array to -- > character arr array or structure array (because the comparison method is inconsistent with the integer comparison method), such arrays cannot be sorted in the bubble sorting we have edited at present

So we can conclude that the bubble sort we write everyday can't sort various types of variables

Let's introduce today's protagonist qsort function

3, Use and advantages of qsort function

1. Header file required by qsort function

2. Parameters and return types required by qsort function

We see that the return type of the qsort function is void (empty type)

Then we look at the parameters required by the function one by one

a.base is the first address of the array to be sorted

b.The number of elements of the array to be sorted

c.Size of array elements in bytes

d.

Here we need to write a comparison function ourselves

Here, we don't know all the information of the array (type, number of elements and element size), so here we uniformly adopt the type of size_t (unsigned number) for the number of elements and element size. For the address of the first element of the array, because we don't know what type of array we need to arrange, we use void * to receive the address of the first element of the array (void * can be converted to any class pointer type). Because we don't know the element type, we write the comparison function ourselves as void * type to receive the addresses of two variables, and pass in the address of the comparison function we write ourselves in the qsort function.

e. The return value of the cmp function written by yourself

Therefore, the return values are arranged in ascending order greater than 0 and descending order less than 0, which is the same as the code of the if conditional judgment statement in our bubble sorting to judge the size relationship with the subsequent elements

The code of the comparison function is as follows:

int cmp_int(const void* e1, const void* e2)
{
	return *(int*)e1 - *(int*)e2;
}

As shown in the figure above, we compare two integers

Because e1 is the address of the stored variable type and is of void * type, we need to forcibly convert e1 to the comparison type we need. The above code compares integer data, so we forcibly convert e1 to int * type, and finally dereference the element. The same is true for e2. The size of the last two returned elements is subtracted from 0

Full code of qsort function:

#include <stdio.h>
#include <stdlib.h>
int cmp_int(const void* e1, const void* e2)
{
	return *(int*)e1 - *(int*)e2;
}
int main()
{
	int arr[10] = { 2,7,1,3,4,5,6,9,8,0 };
	int sz = sizeof(arr) / sizeof(arr[0]);
	qsort(arr, sz, sizeof(arr[0]), cmp_int);
	int i = 0;
	for (i = 0; i < sz; i++)
	{
		printf("%d ", arr[i]);
	}
	return 0;
}

As shown in the code above, we arrange the array in ascending order

If we need to change to the descending order, we just need to exchange the positions of E1 and E2

Let's try to use the qsort function to sort the structure

The code is as follows: (sorted by name) we can use the qsort function to transform the comparison function to realize any type of comparison. Here, we can't use addition and subtraction for string comparison. We need to use the library function strcmp. Other judgment methods of the same integer type are consistent

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct stu 
{
	char name[20];
	int age;
};
int cmp_name(const void* e1, const void* e2)
{
	return strcmp(((struct stu*)e1)->name, ((struct stu*)e2)->name);
}
int main()
{
	struct stu s[3] = { {"zhangsan",11},{"lisi",10},{"wangwu",12} };
	int sz = sizeof(s) / sizeof(s[0]);
	qsort(s, sz, sizeof(s[0]), cmp_name);
	int i = 0;
	for (i = 0; i < sz; i++)
	{
		printf("%d %s\n", s[i].age, s[i].name);
	}
	return 0;
}

Sort by age: (just change the comparison function) age is an integer, and the size of elements can be determined by direct subtraction

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct stu 
{
	char name[20];
	int age;
};
int cmp_age(const void* e1, const void* e2)
{
	return ((struct stu*)e1)->age-((struct stu*)e2)->age;
}
int main()
{
	struct stu s[3] = { {"zhangsan",11},{"lisi",10},{"wangwu",12} };
	int sz = sizeof(s) / sizeof(s[0]);
	qsort(s, sz, sizeof(s[0]), cmp_age);
	int i = 0;
	for (i = 0; i < sz; i++)
	{
		printf("%d %s\n", s[i].age, s[i].name);
	}
	return 0;
}

4, Implementation of qsort function by bubble sorting simulation

#include <stdio.h>
int cmp_int(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++;
	}
}
void Bubblesort(void* base,size_t num,size_t width,int(*cmp)(const void* e1, const void* e2))
{
	size_t i = 0;
	size_t j = 0;
	for (j = 0; j < num - 1; j++)
	{
		for (i = 0; i < num - j - 1; i++)
		{
			if (cmp((char*)base+i*width,(char*)base+(i+1)*width) > 0)
			{
				swap((char*)base + i * width, (char*)base + (i + 1) * width, width);
				
			}
		}
	}

}
int main()
{
	int arr[10] = { 2,7,1,3,4,5,6,9,8,0 };
	int sz = sizeof(arr) / sizeof(arr[0]);
	Bubblesort(arr, sz, sizeof(arr[0]), cmp_int);
	int i = 0;
	for (i = 0; i < sz; i++)
	{
		printf("%d ", arr[i]);
	}
	return 0;
}

The code above is the qsort function implemented by bubble sorting simulation

We analyze:

1.

We can see that the code of the main function is almost the same, and only the name of the sorted function has changed (it has become our own Bubblesort)

2. User defined Bubblesort function

Here, because we don't know what type of array is arranged, how large the array is, and the size of each element, we can directly use the parameter style of qsort function for the parameter type here

The number of times and elements of bubble sort are written in the same way as ordinary bubble sort

The conditional judgment if statement here is different from the ordinary bubbling statementThe effect of this statement is the same, that is, judge the size of two adjacent elements

Parse this statement:

1. Why does forced type conversion use char*

Because char * is the smallest pointer type, char*+1 type skips one byte every time. Because we don't know the array type to be sorted, we choose char * type, which is the smallest and smallest method. After the forced type conversion of the first element of the array, If we don't use int *, int*+1 skips four bytes. If the sorted array is of char type, we can't get all the element addresses of the array, so we need to take the smallest and smallest type to get the address of the array element

2. Put the two variables we obtained into the previously edited comparison function and compare the size of the two numbers

3. If the conditions of our if conditional sentence are met, we will enter the statement of element exchange

This statement is similar to that in our ordinary bubble sortThe same effect is to exchange the size of two elements, but we use a function to realize the function of changing order.

4.swap function

 

For the parameters here, we use two pointers to receive the addresses of two variables, and we also need the size of the element

The code of the exchange element is as follows:

 

Final operation result:

Let's try whether the structure can be sorted with the bubble sort we just wrote

#include <stdio.h>
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++;
	}
}
void Bubblesort(void* base,size_t num,size_t width,int(*cmp)(const void* e1, const void* e2))
{
	size_t i = 0;
	size_t j = 0;
	for (j = 0; j < num - 1; j++)
	{
		for (i = 0; i < num - j - 1; i++)
		{
			if (cmp((char*)base+i*width,(char*)base+(i+1)*width) > 0)
			{
				swap((char*)base + i * width, (char*)base + (i + 1) * width, width);
				
			}
		}
	}

}
struct stu
{
	char name[20];
	int age;
};
int cmp_age(const void* e1, const void* e2)
{
	return ((struct stu*)e1)->age-((struct stu*)e2)->age;
}
int main()
{
	struct stu s[3] = { {"zhangsan",11},{"lisi",10},{"wangwu",12} };
	int sz = sizeof(s) / sizeof(s[0]);
	/*qsort(s, sz, sizeof(s[0]), cmp_name);*/
	Bubblesort(s, sz, sizeof(s[0]), cmp_age);
	int i = 0;
	for (i = 0; i < sz; i++)
	{
		printf("%d %s\n", s[i].age, s[i].name);
	}
	return 0;
}

By age

#include <stdio.h>
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++;
	}
}
void Bubblesort(void* base,size_t num,size_t width,int(*cmp)(const void* e1, const void* e2))
{
	size_t i = 0;
	size_t j = 0;
	for (j = 0; j < num - 1; j++)
	{
		for (i = 0; i < num - j - 1; i++)
		{
			if (cmp((char*)base+i*width,(char*)base+(i+1)*width) > 0)
			{
				swap((char*)base + i * width, (char*)base + (i + 1) * width, width);
				
			}
		}
	}

}
struct stu
{
	char name[20];
	int age;
};
int cmp_name(const void* e1, const void* e2)
{
	return strcmp(((struct stu*)e1)->name, ((struct stu*)e2)->name);
}
int main()
{
	struct stu s[3] = { {"zhangsan",11},{"lisi",10},{"wangwu",12} };
	int sz = sizeof(s) / sizeof(s[0]);
	Bubblesort(s, sz, sizeof(s[0]), cmp_name);
	/*Bubblesort(s, sz, sizeof(s[0]), cmp_age);*/
	int i = 0;
	for (i = 0; i < sz; i++)
	{
		printf("%d %s\n", s[i].age, s[i].name);
	}
	return 0;
}

By name:

summary

These are some ways to use the qsort function and use bubble sorting to simulate the implementation of the qsort function

Topics: C