Detailed explanation of two-dimensional array and qsort's compar function

This article was summarized when doing LeetCode topic # 524, mainly to make up for the three aspects of the two-dimensional array, the storage method of multiple strings, and the use of qsort.

# 524. Match the longest word in the dictionary by deleting letters

 

Question type

Double pointer

Summary

1. About the usage of two-dimensional array

  • The concept of a two-dimensional array: a two-dimensional array is similar to a one-dimensional array, except that its array elements are one-dimensional arrays. In fact, a [0], a [1] ... are the first addresses of a one-dimensional array. To understand the concept of a two-dimensional array, you need to understand the memory model of a two-dimensional array, for int a[4][3]example,
    [___|___|___][___|___|___][___|___|___][___|___|___]
    ^            ^            ^            ^               
    a           a+1           a+2          a+3          int **
    a[0]        a[1]          a[2]         a[3]         int *
    a[0][0]     a[1][0]       a[2][0]      a[3][0]      int
    下标与指针的关系和一维数组相同:            
    a[1] = *(a+1)  a[2] = *(a+2) ...                           
    a[1][1] = *(a[1]+1)  a[1][2] = *(a[1]+2) ...         
  • Note that the addresses of a [0] and array element a [0] [0] are numerically the same, but they are not the same address (pointer) type
  • The array name of a two-dimensional array: In the int a[3][4]array name a is a pointer to the first one-dimensional array, (a + 1) points to the second ... and a [0] = * (a + 0) = * a is the array name of the first one-dimensional array, a [1] = * (a + 1) is the array name of the second one-dimensional array ...
  • How to declare a pointer to an integer array? : int (*p)[4], Here you must specify the number of elements of the array you want to point to, so that pthe correct offset can be performed during the operation, such as p++increasing the address 4*sizeof(int). You can use the pointer to the array to operate on the two-dimensional array, such as
    int a[3][4];
    int (*p)[4] = a;
    p++;
    ...
    If you want a pointer to access the elements in the two-dimensional array one by one, you can declare it like this: int *p = &a[0][0]orint *p = a[0]
  • When multi-dimensional array is used as the function parameter, how to declare the corresponding function parameter? : The multi-dimensional array name as a function parameter is transferred in the same way as a one-dimensional array-the actual transfer is a pointer to the first element of the array. First look at the case where the array name of a one-dimensional array is used as a function parameter:
    int a[10];
    ...
    func1( a );
    Here, the function prototype of func1 can be any of the following 2 types:
    void func1( int *vec );
    void func1( int vec[] );
    Look at the situation of the two-dimensional array:
    int b[4][10]
    ...
    func2( b );
    The function prototype of func2 can be declared as follows:
    void func2( int (*mat)[10] );
    void func2( int mat[][10] );
    Note that the following statement is wrong: void func2( int **mat );. Although the name of the two-dimensional array belongs to the pointer to the pointer, it points to the pointer (first address) of the one-dimensional array, which contains the nature of the one-dimensional array-the number of elements, and the int **mat;pointer to the integer variable (address ). If the two-dimensional array name bpassed to the function void func2( int **mat )is generated when the arithmetic operation performed mat problem: mat++only the address offset sizeof(int), which is equivalent to an array mat b [4] [1], if so void func2( int (*mat)[10] );, then mat++will address Offset 10*sizeof(int).
  • How to store a set of strings? : There are two methods, one is to use an array of pointers, the declaration and initialization are as follows:
    char *ps[] = { "just", "do", "it" };
    or
    char *ps[3] = { "just", "do", "it" };
    Using this method, the array elements are pointers to individual strings, and the 3*sizeof(char *)
    other method is to use a two-dimensional array. The declaration and initialization are as follows:
    char s[3][10] = { "just", "do", "it" };
    Using this method, the contents of the string are all stored in a two-dimensional array, the size of the occupied space is 3*10*sizeof(char), this method takes up more space, especially when the length of the string is very different, there will be a lot of wasted space.
  • What is the value of sizeof (array name)? : Although the array name is a pointer, sizeof (array name) is not the bytes occupied by a pointer, but the number of bytes occupied by the entire array. E.g:
    char s[10][10];
    int i = sizeof( s );
    The value of i is 100, not 32 (determined by the specific number of pointers)

2. About the definition of cmp function in
qsort qsort is used to sort the array elements. The prototype of the function is void qsort (void* base, size_t num, size_t size, int (*compar)(const void*,const void*));where compar is the comparison function. The qsort function will pass the pointers of the two array elements to be compared to it and proceed according to its return value Sort. Since the element pointer is passed to the compar function, its internal implementation generally has the following form:

int compareMyType (const void * a, const void * b)
{
  if ( *(MyType*)a <  *(MyType*)b ) return -1;
  if ( *(MyType*)a == *(MyType*)b ) return 0;
  if ( *(MyType*)a >  *(MyType*)b ) return 1;
}

That is void *, the pointer of the type must be converted back to the pointer type of the array element, and then compared, such as the sorting of integer arrays:

int compar( const void *a, const void *b )
{
    return ( *(int*)a - *(int*)b );  //从小到大排序
}
int a[4] = { 3, 1, 4, 5 };
qsort( a, 4, sizeof(int), compar );

Another example is the comparison of string arrays:

int compar( const void *a, const void *b )
{
    //注意,由于比较的是二维数组的元素,因此qsort传递给
    //compar的是数组元素的指针,也就是各一维数组的指针,
    //其类型和二维数组名相同,为指向字符数组的指针,其
    //声明方式为:char (*p)[5],因此类型转换为(char (*)[5]),
    //由于strcmp需要的是字符串的指针,因此需要解引用。
    //强制转换后a的类型为指向字符数组的指针,因此解引用
    //后类型为字符数组的数组名(首地址),也是字符串指针
    //,于是就可以给strcmp使用了。
    return strcmp( *(char (*)[5])a, *(char (*)[5])b );
}
char a[3][5] = { "go", "to", "do" };
qsort( a, 3, 5*sizeof(char), compar );

Another example is the sorting of arrays of character pointers (string literals):

int compar( const void *a, const void *b )
{
    //由于数组元素为字符指针类型,传递给
    //compar的是字符指针的指针(地址),
    //因此应先转换回类型char **
    return strcmp( *(char **)a, *(char **)b );
}
char *a[3] = { "go", "to", "do" };
qsort( a, 3, sizeof(char *), compar );

Guess you like

Origin www.cnblogs.com/uestcliming666/p/12728742.html