"Bubble sorting idea" implements the qsort function

Table of contents

 1. Bubble sorting

 principle:

 Example:

2. Implement qsort

Review qsort function 

 parameter:

structure:

 Comparison function:

Exchange function: 

 Output function:

3. Complete version of sorting integer data: 

 4. Sorting structure data:

 explain:


 1. Bubble sorting

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

 principle:

  • bubble_sort The function accepts an array of integers  arr and the size of the array  sz as parameters.

  • The outer loop  for (i = 0; i < sz-1; i++) controls how many rounds of comparison and exchange are required. sz-1 Rounds are required because each round moves the largest element of the current unsorted section to the end  .

  • The inner loop  for (int j = 0; j < sz - 1 - i; j++) is used to iterate over the elements of the currently unsorted section.

  • In the inner loop, by comparing  the sum arr[j] of  two adjacent elements arr[j + 1], if the order is wrong ( arr[j] > arr[j + 1]), their positions are swapped.

  • With a swap operation, each round moves the largest element of the current unsorted section to the end.

 Example:

Now, let us use a simple example to illustrate the process of bubble sort.

Suppose we have an array of integers  arr = {5, 3, 8, 2, 1}.

Initial state:

5  3  8  2  1

first round:

  • Compare  5 and  3, they are in the wrong order, swap their positions.
3  5  8  2  1
  • Comparing  5 the  8sums, they are in the correct order and do not need to be swapped.
  • Compare  8 and  2, they are in the wrong order, swap their positions.
3  5  2  8  1
  • Compare  8 and  1, they are in the wrong order, swap their positions.
3  5  2  1  8

second round:

  • Comparing  3 the  5sums, they are in the correct order and do not need to be swapped.
  • Compare  5 and  2, they are in the wrong order, swap their positions.
3  2  5  1  8
  • Compare  5 and  1, they are in the wrong order, swap their positions.
3  2  1  5  8
  • Comparing  5 the  8sums, they are in the correct order and do not need to be swapped.

Round 3:

  • Compare  3 and  2, they are in the wrong order, swap their positions.
2  3  1  5  8
  • Compare  3 and  1, they are in the wrong order, swap their positions.
2  1  3  5  8
  • Comparing  3 the  5sums, they are in the correct order and do not need to be swapped.
  • Comparing  5 the  8sums, they are in the correct order and do not need to be swapped.

Round 4:

  • Compare  2 and  1, they are in the wrong order, swap their positions.
1  2  3  5  8
  • Comparing  2 the  3sums, they are in the correct order and do not need to be swapped.
  • Comparing  3 the  5sums, they are in the correct order and do not need to be swapped.
  • Comparing  5 the  8sums, they are in the correct order and do not need to be swapped.

Finally, the array has been sorted in ascending order:

1  2  3  5  8

This is the process of bubble sort. Through multiple comparisons and exchanges , the largest element will gradually move to the end until all elements are sorted. Now you understand how bubble sort works . Next, we use this idea to try to implement the function of qsort function.

2. Implement qsort

Review qsort function 

 By the way, if you forget the qsort function, take a look at the article I wrote before!

 Pointer (2)—qsort function

 parameter:

 We name the custom function that implements the same functionality bubble_sort.

 Okay, now let me start with the parameters required by the qsort function   

 The parameters of the bubble sort function are int type, so how can we pass any type of parameters like the qsort function?

void bubble_sort(int arr[], int sz)

We can see that the variables that need to be sorted in the qsort function definition are defined as "void*" type

void qsort(void* base, //指向了需要排序的数组的第一个元素
           size_t num, //排序的元素个数
           size_t size,//一个元素的大小,单位是字节
           int (*cmp)(const void*, const void*)//函数指针类型
           这个函数指针指向的函数,能够比较base指向数组中的两个元素);

 So we also define the parameters of the bubble sort function as "void*" type.

At the same time, we also imitate qsort and give the same parameters to the bubble_sort custom function that simulates the same function .

void bubble_sort(void* base, int num, int size, int (*cmp)(const void*, const void*)

These parameters are very helpful for us to compare sizes and swap positions  later .

structure:

Let's take a look at where adjustments need to be made inside the bubble function.

void bubble_sort(void* base, int num, int size, int (*cmp)(const void*, const void*))
{
    for (i = 0; i < sz-1; i++) {
	    for (int j = 0; j < sz - 1 - i; j++) {
		    if (arr[j] > arr[j + 1]) {
		   	    int tmp = arr[j + 1];
			    arr[j + 1] = arr[j];
			    arr[j] = tmp;
		    }
	    }
    }
}

 The two for loops iterate over the elements of the passed in array that need to be compared, without changing them.

Inside the second nested loop, we need to compare and adjust the array elements passed in. Because the parameters we pass should be addresses, we need to  replace arr[j] and arr[j + 1]  with the address form, which is  base + j sum base + (j + 1) .

 Comparison function:

At the same time, comparing the size of two elements should not be limited to > or <. For example, structures cannot be compared using the greater than or less sign .

Therefore, if we want to compare different types of parameters, we need to switch to the method of difference subtraction , and compare the size by the result being greater or less than 0.

From this, we use the same method as in the qsort function to construct a function that compares integer arrays.

int cmp_int(const void* p1, const void* p2)
{
	return (*(int*)p1 - *(int*)p2);
}
  • When comparing two elements, what we need to pass to  cmp the function are two addresses, the addresses with subscripts  j and  j + 1 . Since  base the type of is  void*, we need to do a type conversion, it's better to cast it to  char* type since  char type takes up one byte.
  • In order to be able to handle different types of data and compare the size of two adjacent elements, parameters  size become very important.
  • We can jump to the next pair of elements that need to be compared by different types of element sizes (number of bytes), so that we can ensure that different types of data are handled correctly when comparing. We need to  j multiply the size of each element in order to smoothly jump to the next pair of elements of the corresponding type. size

Exchange function: 

  After comparing the sizes of the two elements, if they are arranged in ascending order, the larger number needs to be exchanged with the smaller number (the descending order is reversed).

 In the original structure, this method cannot exchange elements of different types . We consider writing a Swap function to exchange elements of different types.

int tmp = arr[j + 1];
arr[j + 1] = arr[j];
arr[j] = tmp;

Define the parameters of the Swap function as the addresses of the two elements that need to be swapped and the number of bytes of the elements ,

 By exchanging bytes we can smoothly exchange elements of different types.

Explanation: The parameters buf1 and buf2 passed in are both char* type addresses. The byte size of the corresponding type (i.e. parameter size) is cycled and incremented after exchanging one byte until all bytes of the corresponding element type are exchanged. The elements are exchanged. Finish.

void Swap(char* buf1, char* buf2, int size)
{
	int i = 0;
	char tmp = 0;
	for (i = 0; i < size; i++)
	{
        tmp = *buf1;   // 保存 buf1 指向的元素的值到临时变量 tmp
        *buf1 = *buf2; // 将 buf2 指向的元素的值赋给 buf1 指向的元素
        *buf2 = tmp;   // 将 tmp 中保存的值赋给 buf2 指向的元素
        buf1++;        // 移动 buf1 的指针,指向下一个元素
        buf2++;        // 移动 buf2 的指针,指向下一个元素
	}
}

 The format of the parameters when passed in is the same as when passed into the comparison function.

Swap((char*)base + j * size, (char*)base + (j + 1) * size, size);

 Output function:

Simply write an output function to easily verify whether the program runs successfully.

void Print(int arr[], int sz)
{
	for (int i = 0; i < sz; i++) {
		printf("  %d", arr[i]);
	}
	printf("\n");
}

3. Complete version of sorting integer data: 

Finally, embed the comparison function cmp_int and the exchange function Swap into the bubble_sort function, call Print output, and initialize it with test1.

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

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

void bubble_sort(void* base,int num,int size,int (*cmp)(const void*,const void*))
{
	int i = 0;
	for (i = 0; i < num - 1; i++) {
		for (int j = 0; j < num - 1 - i; j++) {
			if (cmp((char*)base + j * size, (char*)base + (j + 1) * size) > 0)
            {
				Swap((char*)base + j * size, (char*)base + (j + 1) * size, size);
            }
		}
	}
}

void Print(int arr[], int sz)
{
	for (int i = 0; i < sz; i++) {
		printf("  %d", arr[i]);
	}
	printf("\n");
}

void test1()
{
	int arr[] = { 54,25,333,32,3 };
	int sz = sizeof(arr) / sizeof(arr[0]);
	bubble_sort(arr, sz, sizeof(arr[0]), cmp_int);
	Print(arr, sz);
}

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

Run successfully, sorting successful! !

 4. Sorting structure data:

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

void bubble_sort(void* base, int num, int size, int (*cmp)(const void*, const void*))
{
	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*size, (char*)base+(j+1)*size)>0)
			{
				Swap((char*)base + j * size, (char*)base + (j + 1) * size, size);
			}
		}
	}

}

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


void print_struct_array(struct Stu* arr, int num)
{
    for (int i = 0; i < num; i++)
    {
        printf("Name: %s, Age: %d\n", arr[i].name, arr[i].age);
    }
    printf("\n");
}


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


void test2()
{
	struct Stu arr[] = { {"zhangsan", 20}, {"lisi", 50},{"wangwu", 15} };
	int sz = sizeof(arr) / sizeof(arr[0]); 
	bubble_sort(arr, sz, sizeof(arr[0]), cmp_stu_by_age);
}


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


void test3()
{
	struct Stu arr[] = { {"zhangsan", 20}, {"lisi", 50},{"wangwu", 15} };
	int sz = sizeof(arr) / sizeof(arr[0]);
	printf("%d\n", sizeof(struct Stu));
	bubble_sort(arr, sz, sizeof(arr[0]), cmp_stu_by_name);
}

int main()
{
	test2();
	test3();

	return 0;
}

 explain:

  1. cmp_stu_by_age function : This function is a comparison function used to compare students based on their age. It returns a negative, zero, or positive number when comparing two student structures to indicate whether the first student should be before, equal to, or after the second student.

  2. cmp_stu_by_name function : This is another comparison function used to compare students based on their names. It uses strcmpa function to compare two students' names, again returning a negative, zero, or positive number.

  3. print_struct_array function : This function accepts an array of structures and the size of the array as parameters, and prints the name and age of each structure in the array. This function is used to output the sorted results.

In  main the function:

  • test2 The function sorts the student structure array according to age and outputs the sorting result.
  • test3 The function sorts the same student structure array by name and outputs the sorted results.

The result is as follows: 

Guess you like

Origin blog.csdn.net/m0_73800602/article/details/132843867