Detailed introduction to the use of the C language sort() function

The qsort() function (quick sort) is a quick sort algorithm that can sort arrays of any data type, including integers, floating point types, strings and even custom structure types.

The following figure shows the meaning of the 4 parameters

 qsort(void *__base, size_t __nel, size_t __width,int (* _Nonnull __compar)(const void *, const void *));

1. void*base (first element address)

If we want to sort an array, we must first know where to start sorting, so first pass the address of the first element to the qsort function. 

2.size_t nell (number of elements)

We also need to know where the array ends, but due to the uncertainty of sorting, we don't know the address of the last element, so the number of elements is passed to the qsort function.

3.size_t width (element byte size)

We know that the qsort function can sort a set of data of any type, so we use void* type pointers to receive elements, but void* type pointers cannot perform addition and subtraction operations, so they cannot be moved.

So how to manipulate variables inside the function?

We can cast the void* type pointer to the char* type pointer and then manipulate the elements. Because the unit of moving a char* type pointer is one byte, so when you know the byte size of the element to be operated, you can let the char* type pointer move the byte to the next element, and the pointer can point to that element too.

4.int (* _Nonnull __compar)(const void *, const void *)) (comparison function)

How do we sort a set of data? For example, you can give integer data from small to large, or you can give floating-point data from large to small, or you can compare the size of strings or the length of strings. These we have to write a comparison function.

specific use

To use the qsort function we need to reference a header file <stdlib.h>

#include <stdlib.h>

For example, if we want to sort an array of integer elements


#include <stdio.h>
#include <stdlib.h>

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

int main()
{
    int arr[5] = {5, 2, 1, 4, 3};
    qsort(arr, 5, sizeof(arr[0]), compar);
    for (int i = 0; i < 5; i++){
        printf("%d ", arr[i]);
    }
    return 0;
}

The printed result:

You can see the ascending order, and changing to descending order only needs to change the content in compar.


#include <stdio.h>
#include <stdlib.h>

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

int main()
{
    int arr[5] = {5, 2, 1, 4, 3};
    qsort(arr, 5, sizeof(arr[0]), compar);
    for (int i = 0; i < 5; i++) {
        printf("%d ", arr[i]);
    }
    return 0;
}

It can be seen that adding a negative sign to the return value can change the order of arrangement, so what is the reason? Next, I will use the bubble sort method to implement this function for everyone.

#include <stdio.h>
#include <stdlib.h>

//交换函数的实现
void Swap(char *buf1, char *buf2, int width){
    while (width)
    {
        char box = *buf1;
        *buf1 = *buf2;
        *buf2 = box;
        buf1++;
        buf2++;
        width--;
    }
}

//比较函数的实现
int cmp(const void *e1, const void *e2){
    return *(int *)e1 - *(int *)e2;
}

void bubble_sort(void *base, int sz, int width, int (*cmp)(const void *, const void *)){
    int i, j = 0;
    for (i = 1; i < sz; i++){
        for (j = 0; j < sz - i; j++){
            // 调用cmp函数,这里可以规定函数排序的方式(升序or降序)
            if (cmp((char *)base + j * width, (char *)base + (j + 1) * width) > 0){
                // 满足上述条件,开始排序
                Swap((char *)base + j * width, (char *)base + (j + 1) * width, width);
            }
        }
    }
}

int main()
{
    int arr[5] = {4, 3, 1, 2, 5};
    int sz = sizeof(arr) / sizeof(arr[0]);
    bubble_sort(arr, sz, sizeof(arr[0]), cmp);
    for(int i=0; i<5; i++){
        printf("%d ",arr[i]);
    }
    return 0;
}

 Therefore, according to the internal implementation of the above function, it can be concluded that if the value of return is greater than 0, then it will be exchanged and sorted. Then if you want to sort in the opposite direction, you only need to make the value of return negative, and exchange if the previous number is smaller than the next number, and sort in descending order.

Various types of cmp function implementations (except for integers, which are included above)

1. Floating point

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

2. Compare string size

int cmp(const void *e1, const void *e2){
    return strcmp((char*)e1,(char*)e2);
}

3. Compare the length of characters

int cmp(const void *e1, const void *e2){
    return strlen((char*)e1) - strlen((char*)e2);
}

4. Compare structure variables

int cmp(const void *e1, const void *e2){
    return (int)(((stu*)e1)->weight - ((stu*)e2)->weight);
}

Guess you like

Origin blog.csdn.net/2203_76113052/article/details/128696768