2次元配列とqsortの比較関数の詳細な説明

この記事は、主に2次元配列の3つの側面、複数の文字列の格納方法、およびqsortの使用を補うために、LeetCodeトピック#524を実行するときにまとめられました。

524.文字を削除して、辞書で最も長い単語と一致させる

 

質問タイプ

ダブルポインター

まとめ

1. 2次元配列の使用について

  • 2次元配列の概念:2次元配列は、配列要素が1次元配列であることを除いて、1次元配列に似ています。実際、[0]、[1] ...は1次元配列の最初のアドレスです。2次元配列の概念を理解するには、int a[4][3]たとえば、2次元配列のメモリモデルを理解する必要があります
    [___|___|___][___|___|___][___|___|___][___|___|___]
    ^            ^            ^            ^               
    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) ...         
  • [0]と配列要素a [0] [0]のアドレスは数値的に同じですが、同じアドレス(ポインター)タイプではないことに注意してください
  • 2次元配列のint a[3][4]配列名配列名では、aは最初の1次元配列へのポインター、(a + 1)は2番目の...を指し、a [0] = *(a + 0)= * aは最初の1次元配列の配列名、a [1] = *(a + 1)は2番目の1次元配列の配列名...
  • 整数配列へのポインタを宣言する方法は?int (*p)[4]、ここで、アドレスpp++増やすなどの操作中に正しいオフセットを実行できるように、ポイントする配列の要素数を指定する必要があります4*sizeof(int)配列へのポインタを使用して、次のような2次元配列を操作できます。
    int a[3][4];
    int (*p)[4] = a;
    p++;
    ...
    あなたは要素を一、二次元配列へのポインタずつにアクセスしたい場合は、宣言することができますint *p = &a[0][0]int *p = a[0]
  • 多次元配列を関数パラメーターとして使用する場合、対応する関数パラメーターを宣言するにはどうすればよいですか?:関数パラメーターとしての多次元配列名は、1次元配列と同じ方法で転送されます。実際の転送は、配列の最初の要素へのポインターです。最初に、1次元配列の配列名が関数パラメーターとして使用されている場合を見てください。
    int a[10];
    ...
    func1( a );
    ここで、func1の関数プロトタイプは、次の2つのタイプのいずれかになります。
    void func1( int *vec );
    void func1( int vec[] );
    2次元配列の状況を見てください。
    int b[4][10]
    ...
    func2( b );
    func2の関数プロトタイプは次のように宣言できます。
    void func2( int (*mat)[10] );
    void func2( int mat[][10] );
    次の文が間違っていることに注意してください:void func2( int **mat );2次元配列の名前はポインターへのポインターに属していますが、1次元配列の性質(要素数)を含む1次元配列のポインター(最初のアドレス)int **mat;と、整数変数(アドレス)へのポインターを指します。 )。二次元アレイ名があればb、関数に渡されたvoid func2( int **mat )演算は、マットの問題を行ったときに生成される:mat++オフセットのみアドレスsizeof(int)アレイマットBに相当するが、[4] [1]、もしそうであればvoid func2( int (*mat)[10] );、次にmat++取り組みますオフセット10*sizeof(int)
  • 文字列のセットを保存する方法は?:2つの方法があります。1つはポインターの配列を使用する方法で、宣言と初期化は次のとおりです。
    char *ps[] = { "just", "do", "it" };
    または
    char *ps[3] = { "just", "do", "it" };
    この方法を使用すると、配列要素は個々の文字列へのポインタであり、3*sizeof(char *)
    もう1つの方法は2次元配列を使用することです。宣言と初期化は次のとおりです。
    char s[3][10] = { "just", "do", "it" };
    この方法を使用すると、文字列の内容はすべて2次元配列に格納されます。占有スペースのサイズはです3*10*sizeof(char)。このメソッドは、特に文字列の長さが非常に異なる場合に多くのスペースを消費し、多くの無駄なスペースが生じます。
  • sizeof(配列名)の値は何ですか?:配列名はポインターですが、sizeof(配列名)はポインターが占めるバイト数ではなく、配列全体が占めるバイト数です。たとえば、次のとおりです。
    char s[10][10];
    int i = sizeof( s );
    iの値は32ではなく100です(特定のポインター数によって決定されます)

2.
qsort でのcmp関数の定義についてqsortは、配列要素をソートするために使用されます。関数のプロトタイプはvoid qsort (void* base, size_t num, size_t size, int (*compar)(const void*,const void*));、comparが比較関数です。qsort関数は、比較される2つの配列要素のポインタを渡し、その戻り値に従って処理します並べ替え。要素ポインタは比較関数に渡されるため、その内部実装は通常、次の形式になります。

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;
}

つまりvoid *、型のポインターを配列要素のポインター型に変換し直してから、整数配列のソートなどの比較を行う必要があります。

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 );

別の例は、文字列配列の比較です。

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 );

別の例は、文字ポインター(文字列リテラル)の配列の並べ替えです。

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 );

おすすめ

転載: www.cnblogs.com/uestcliming666/p/12728742.html
おすすめ