C 将一维数组视为二维数组进行排序
假设我有一个100个元素的一维数组。是否有一种方法可以将此数组视为10x10二维数组,以便对其执行多参数排序。我真的不想将原始数组的内容存储到新的多维数组中,我只想找到一种方法,将一维数组当作二维数组来操作。对于这是否严格合法C11,存在一些争议,但下面这样的代码非常常见:C 将一维数组视为二维数组进行排序,c,arrays,sorting,pointers,C,Arrays,Sorting,Pointers,假设我有一个100个元素的一维数组。是否有一种方法可以将此数组视为10x10二维数组,以便对其执行多参数排序。我真的不想将原始数组的内容存储到新的多维数组中,我只想找到一种方法,将一维数组当作二维数组来操作。对于这是否严格合法C11,存在一些争议,但下面这样的代码非常常见: #include <stdio.h> int a1[100]; int (*a2)[10] = (int (*)[10])a1; int main(int argc, char *argv[]) {
#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[x][y]
替换为a2(x,y)
。或者使用一个函数,但这会增加函数调用的开销(或者生成一个内联的函数)。对于这是否严格合法存在一些争议,但下面这样的代码非常常见:
#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[x][y]
替换为a2(x,y)
。或者使用一个函数,但这会增加函数调用的开销(或者生成一个内联的函数)。当然可以,但这不是一般推荐的方法。无论您使用的是1D阵列还是2D阵列,都只是使用X数量的存储。你可以随意使用那块内存。当需要在该块中存储一个“数组数组”时,您可以通过将该块声明为2D数组来购买便利,但没有强制要求您必须这样做
例如,以100个元素为例,如果1D数组包含100个元素,并且希望在数组中存储10个元素,则只需手动索引子数组,以提供10*sizeof(type)
的倍数,这正是指针算术为您所做的。实际上,您将在1D数组中寻址,就像您声明了一个指向total/n
元素数组的指针,然后分配给n
元素一样。(例如,char(*s)[10];
如果将100个字符的存储划分为10个字符串,则可以进行类比)
举一个简单的100字符数组的例子,您想用它来存储和排序10-10个字符的字符串(9字符+nul终止字符)。您可以简单地声明chars[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]);
}
示例使用/输出
$ ./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阵列只是提供了一种方便的方法,可以避免您自己提出这种寻址方案。当然,您可以,但这不是一般推荐的方法。无论您使用的是1D阵列还是2D阵列,都只是使用X数量的存储。你可以随意使用那块内存。当需要在该块中存储一个“数组数组”时,您可以通过将该块声明为2D数组来购买便利,但没有强制要求您必须这样做
例如,以100个元素为例,如果1D数组包含100个元素,并且希望在数组中存储10个元素,则只需手动索引子数组,以提供10*sizeof(type)
的倍数,这正是指针算术为您所做的。实际上,您将在1D数组中寻址,就像您声明了一个指向total/n
元素数组的指针,然后分配给n
元素一样。(例如,char(*s)[10];
如果将100个字符的存储划分为10个字符串,则可以进行类比)
举一个简单的100字符数组的例子,您想用它来存储和排序10-10个字符的字符串(9字符+nul终止字符)。您可以简单地声明chars[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]);
}
示例使用/输出
$ ./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数组只是提供了一种方便的方式来避免自己提出寻址方案。什么是1D数组上的多参数排序?请给我们举个例子。请拿,读,和。我所说的多参数排序是指我在两种情况下进行排序。多参数排序的一个很好的例子是周期表是如何按周期趋势(如原子半径、电负性等)排序的。您可以从一维数组开始,然后将其视为行或列主形式的二维数组。唯一需要注意的是,你要么需要执行一些记忆巫术(见下面Lee Daniel Crocker的回答),要么,为了合法,实现你自己的索引。例如,对于column major case,假设a
是一个1D整数数组,您可以在(int*a,size\t row,size\t j,size\t nrows){返回一个[j*nrows+i];}
处使用int get\u at(int*a,size\t row,size\t j,size\t nrows){返回一个[j*nrows+i];}?请给我们举个例子。请拿,读,和。我所说的多参数排序是指我在两种情况下进行排序。多参数排序的一个很好的例子是周期表是如何按周期趋势(如原子半径、电负性等)排序的。您可以从一维数组开始,然后将其视为行或列主形式的二维数组。唯一需要注意的是,你要么需要执行一些记忆巫术(参见李丹尼尔·克罗克的answ)