多维数组(如C/ c++)是不规则数组的特殊情况



我曾经和一个朋友讨论过c++和C的多维数组是否是不规则数组的特殊情况。一个观点是

多维数组不是不规则数组,因为多维数组的每个元素都有相同的大小。在不规则数组中,至少有一个元素的大小与同一数组中的另一个元素的大小不同。("如果它不可能被打乱,它就不是一个打乱的数组。").

另一个观点是

多维数组是不规则数组的一种特殊情况,每个元素都有相同的大小。一个不规则的数组可能有不同大小的行,但不是必须的。("A circle is an ellipsis.").

我有兴趣得到一个明确的答案,关于"不规则数组"在计算机科学中的常见定义是什么,以及C和c++多维数组是否是不规则数组。

我不知道不规则数组的"确切定义"应该是什么,但我相信C/c++多维数组绝对不是不规则的。原因如下:

  • 不规则数组是一个术语,指数组的某种"内存存储"方式,使得至少有一对不同大小的行/单元格。
  • C/c++中的
  • 数组非常直接。数组只是为结构(数组)保留的一个"连续块"内存。
  • 其他高级语言可能有不同的实现来节省内存等,但C/c++数组没有。

所以我相信我们不能把C/c++数组称为粗糙的。

(的意见)。

编辑:

这也很大程度上取决于"衣衫褴褛"的"定义"。所以这不是一个定义明确的术语,所以很难得出结论。(应该避免无谓的辩论)。

C多维数组,如果声明为多维数组,则不能被打乱。例如,一个二维数组是一个"数组的数组",每一行都是相同的长度,即使你不使用数组中的每个条目。

int a1[2][3]; // two rows, three columns
int a2[5][8]; // five rows, eight columns
但是,C语言的特点是,你可以使用指针到指针的,就好像是一个2D数组:
int **a3 = malloc(4);
for (i = 0; i < 4; i++)
  a3[i] = malloc(i);

现在a3可以在很多情况下使用,比如2D数组,但肯定是粗糙的。

恕我直言,真正的数组不能被称为粗糙的,但如果你不得不这样做,你当然可以伪造出来……从这个角度来看,你使用的术语似乎并不那么重要。

我认为区别是概念上的。多维数组

T x[d_1][d_2]...[d_N];

表示大小为$prod_i d_i$的连续内存区域,如果您不介意TeX,它是在strides: x[i_1]…[i_N]元素位置i_N美元+ i_ {n} d_N + i_ {2} d_ {n} d_N +……+ i_1 d_2…d_N美元。中间索引可以作为指向各自子数组的指针。

另一方面,粗糙的数组将内存中的内部"维度"与外部"维度"解耦:
T * r[M];
for (size_t i = 0; i != M; ++i)
  r[M] = new T[get_size_at_row(i)];

大小是否实际变化在这里无关紧要,但概念上的区别在于,粗糙数组是数组的数组,而多维数组是一个更加严格和连贯的对象。

在讨论数学对象时,我认为"粗糙的"可能是"数组"的修饰符,专门用来表示次要维度不匹配的对象。所以这是第一个意思,而不是第二个意思。想想这个词的来源——我们不会说一块崭新的手帕"很粗糙,因为它的边缘有可能磨损,但它还没有磨损"。一点也不粗糙。因此,如果我们称一个特定的数组为"粗糙的",我希望它的意思是"不直的"。

然而,在某些上下文中,值得将"不规则数组"定义为"潜在的不规则数组",而不是实际存在不匹配的数组。例如,如果您要编写一个"raggearray"类,那么您不会在类不变量中设计一个保证在某个地方有不匹配大小的类,并且如果有人试图创建一个所有大小相等的类,则一定要抛出异常。这将是荒谬的,尽管事实上,您将调用这个类的实例"粗糙数组"。因此,在这个上下文中,所有元素中大小相等的数组是的一种特殊情况的"不规则数组"。那是第二个意思,而不是第一个。

当然,C或c++的多维数组仍然不是这个类的实例,但它至少可以满足被称为"RaggedArray"的泛型接口的只读部分。这基本上是一个快捷方式,即使我们知道"粗糙"意味着"大小不匹配",在大多数情况下,你只是懒得调用那个类或泛型接口"PotentiallyRaggedArray",只是为了清楚地表明你不会强制必须有一个约束。

类型的特定实例是否具有特定属性与该类型是否允许其实例具有该属性之间存在差异,当我们说类型X的实例"是X"时,我们经常忽略这种差异。类型X的实例可能有这个属性,这个实例没有,所以这个实例实际上也没有可能有这个属性。你对"衣衫褴褛的阵列"的两种含义可以看作是这种差异的一个例子。看看E-Prime人群,还有维特根斯坦(Wittgenstein)的哲学,当我们说一件事"是"另一件不同的事情时,我们会制造出各种混乱。一个实例"不是"一个类型,一个具体的实例不具有与它的实例相同的潜在属性。

具体回答你的问题,我怀疑在计算机科学文献中是否存在普遍接受的一种含义优于另一种含义。当你把它引入到一个给定的作品(一篇学术论文,一个特定图书馆的文档,等等)时,你必须根据自己的目的来定义它。如果我能找到两篇论文,一篇使用每一篇,那么我已经证明了它,但我不能为此烦恼;-)

我的立场是,粗糙数组与多维数组是可区分的,因为它有(必须有!)一个索引,告诉你每个子数组的起始位置。(一个不规则数组还需要一些机制来跟踪每个子数组的大小,虽然知道子数组的大小是一致的,但这不是很普遍)

原则上你可以建立一个索引来连接到一个标准多维数组的子数组

int arr[6][10];                         // <=== Multi-dimensional array
int **ragged = calloc(6,sizeof(int*));  // <=== Ragged array (initially empty)
for (int i=0; i<6 ++i) {
   ragged[i] = arr[i];                  // <=== make the ragged array alias arr
}

现在我有了一个使用相同数据的二维数组和一个二维粗糙数组。

所以不,语言多维数组是而不是是不规则数组的特殊情况

相关内容

  • 没有找到相关文章

最新更新