将一维数组视为二维数组以进行排序

时间:2018-02-15 22:14:59

标签: c arrays sorting pointers

让我们说我有一个包含100个元素的一维数组。有没有办法可以将此数组视为10x10二维数组,因此我可以对其执行多参数排序。我真的不想将原始数组的内容存储到一个新的多维数组中,我只想在一维数组上操作,就好像它是二维的一样。

2 个答案:

答案 0 :(得分:0)

嗯,是的,你可以,但它不是一般推荐的东西。无论您使用的是1D阵列还是使用2D阵列,您只需使用X-storage存储。您可以随意使用该内存块。当需要存储"阵列数组时#34;在这个区块中,您通过将块声明为2D阵列来购买便利,但是没有必要这样做。

例如,以你的100个元素为例,如果你的一维数组包含100个元素并且你希望在数组中存储10个元素,你只需要手动索引提供10 * sizeof(type)倍数的子数组。这正是指针算术为你做的。实际上,您将在1D数组中进行寻址,就好像您已声明指向total/n元素数组的指针,然后为其分配n。 (例如char (*s)[10];如果您要将10个字符串的100个字符存储区分开来进行类比化

获取一个100-char数组的简单示例,您希望用它来存储和排序10-10个char字符串(9-char + nul-terminatedating 字符)。您只需声明char s[100] = "";,然后将字符串存储在s + n * 10的偏移处即可。要对数组进行排序,您可以滚动自己的排序,或者只使用qsort通过提供正确的比较函数对元素进行排序。以下是:

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

#define NROW 10
#define NCOL NROW

/* qsort - string comparison */
int cmpstrings (const void *a, const void *b) {
    return strcmp ((char * )a, (char *)b);
}

int main (void) {

    char s[NROW * NCOL] = "";       /* 1D array 100 chars */

    strcpy (s, "my");               /* fill with 10 strings */
    strcpy (s + NROW, "dog");
    strcpy (s + NROW * 2, "has");
    strcpy (s + NROW * 3, "fleas");
    strcpy (s + NROW * 4, "but");
    strcpy (s + NROW * 5, "the");
    strcpy (s + NROW * 6, "cat");
    strcpy (s + NROW * 7, "doesn't");
    strcpy (s + NROW * 8, "have");
    strcpy (s + NROW * 9, "any");

    printf ("unsorted:\n");
    for (int i = 0; i < NROW; i++)
        printf ("  s[%2d] : %s\n", i, &s[i*NCOL]);

    qsort (s, NCOL, NROW, cmpstrings);  /* qsort strings */

    printf ("\nsorted:\n");
    for (int i = 0; i < NROW; i++)
        printf ("  s[%2d] : %s\n", i, &s[i*NCOL]);

}

注意: strcpy仅用于加载数组中的各个字符串。您可以使用初始化程序中指定的100个字符轻松初始化数组)

例如,您可以使用以下初始化程序并完全取消对strcpy的调用 - 只是更乏味......

    /* initialize 100-char array with 10 sub-arrays of strings */
    char s[] = "my\0       dog\0      has\0      fleas\0    but\0      "
               "the\0      cat\0      doesn't\0  have\0     any\0      "; 

示例使用/输出

$ ./bin/array1dstrings
unsorted:
  s[ 0] : my
  s[ 1] : dog
  s[ 2] : has
  s[ 3] : fleas
  s[ 4] : but
  s[ 5] : the
  s[ 6] : cat
  s[ 7] : doesn't
  s[ 8] : have
  s[ 9] : any

sorted:
  s[ 0] : any
  s[ 1] : but
  s[ 2] : cat
  s[ 3] : doesn't
  s[ 4] : dog
  s[ 5] : fleas
  s[ 6] : has
  s[ 7] : have
  s[ 8] : my
  s[ 9] : the
只要您不尝试访问有效块之外的内存,C就不会对使用内存块的方式施加任何限制。您可以使用实现该目的的寻址方案。 2D阵列只是提供了一种方便的方法,可以避免不得不自己提出这种寻址方案。

答案 1 :(得分:-1)

对于这是否是严格合法的C11存在争议,但下面的代码非常普遍:

#include <stdio.h> 

int a1[100]; 
int (*a2)[10] = (int (*)[10])a1; 

int main(int argc, char *argv[]) { 
        for (int i = 0; i < 100; i += 1) a1[i] = i + 1; 

        for (int i = 0; i < 10; i += 1) { 
                for (int j = 0; j < 10; j += 1) { 
                        printf("%2d ", a2[i][j]); 
                } 
                printf("\n"); 
        } 
} 

您可以通过将a2替换为:

来使其严格符合,但不太方便
#define a2(x,y) a1[10*(x)+(y)]

然后将a2[x][y]替换为a2(x,y)。或者使用一个函数,但这会花费你的函数调用开销(或者创建一个inline函数)。