在C中声明和定义但不初始化数组的时间复杂度是多少?问题的答案是什么原因?
我对编译和运行时的时间复杂度感兴趣,但运行时间更长。
以下是具有此类数组的程序示例:
int main ()
{
int n[ 10 ]; /* n is an array of 10 integers */
return 0;
}
如果它不是O(1),常数时间,是否有一种语言可以在恒定时间内声明和定义数组?
答案 0 :(得分:3)
这是一个奇怪且可能无法回答的问题。通常是复杂性分析和"大O"符号应用于算法,而不是实现。但在这里,你基本上完全要求实现,以及非算法,"噪声"或者"开销"分配数组的活动。
定义和声明是编译时的概念,我从来没有听说过大O应用于编译时活动。
在运行时,可能需要做一些工作才能使阵列弹出,无论它是否已初始化。如果它是本地("堆栈")数组,操作系统可能必须在内存中为新功能的堆栈帧分配和寻呼,这可能或多或少是O(n) )数组的大小。但是如果堆栈已经存在,它将是O(0),即空闲。
如果数组是静态的和/或全局的,另一方面,它只需要分配一次。但是,操作系统必须再为它分配内存,这可能是O(n)。操作系统可能会也可能不会将内存分页 - 取决于您是否对阵列执行任何操作,以及操作系统的VM算法。 (一旦你开始谈论VM性能,定义和思考就变得非常棘手,因为开销可能会以各种方式与其他进程共享。)
如果数组是全局的或静态的,并且如果你没有初始化它,C表示它已初始化为0,C运行时库和/或操作系统为你做单向或另一种,几乎肯定会在某种程度上是O(n) - 尽管如此,它可能最终会以各种复杂或不可测量的方式与其他活动重叠或共享。
答案 1 :(得分:2)
该语言未指定此内容。但是在典型的实现中,块中所有局部变量的空间仅通过在进入该块时将所有变量的总大小调整为堆栈指针来分配,即O(1)。数组只包含在总大小中,并在编译时计算。在进入块时不分配VLA,分配被延迟到声明的执行(因为它取决于必须首先分配的变量),但它仍然只是调整SP寄存器的O(1)操作。
我认为许多实现在进入函数时实际上为函数分配了所有空间,而不是为每个块调整SP。但是,存在于不重叠的块中的变量可以在堆栈帧中共享相同的存储器。但这与提出的问题并不真正相关,除非你想知道
之间是否存在差异int a[10];
int b[10];
// code that uses a and b
和
int a[10];
{
int b[10];
// code that uses a and b
}
每个变量的编译时复杂度为O(1)(它只需要查找数据类型的大小,如果它是一个数组,则乘以大小),所以O(n)其中n是数字局部变量。
答案 2 :(得分:1)
在C中,在运行时(无论是标量还是数组)实例化变量的成本(通常)在噪声中是降低的,尽管它实际上取决于底层平台。例如,通常只需调整堆栈指针即可在x86平台上为auto
变量留出空间:
subq $X, %rsp
其中 X
是函数中所有局部变量所需的存储量。因此, X
是4还是4K 1 需要相同的时间。
可以从程序映像本身中分配static
个变量的存储,这样一旦程序加载到内存中,存储就会被搁置(使其有效地为零)运行时的成本)。
或不。
Big O符号在这里并不适用;根据实施情况,分配存储的确切机制可能会因批次而异,其中大部分都是您无法控制的。空间通常是限制因素,而不是时间。
<小时/>