Go `附加`复杂性
在Go编程语言中,这个循环的计算复杂度是多少Go `附加`复杂性,go,Go,在Go编程语言中,这个循环的计算复杂度是多少 var a []int for i := 0 ; i < n ; i++ { a = append(a, i) } var a[]int 对于i:=0;i
var a []int
for i := 0 ; i < n ; i++ {
a = append(a, i)
}
var a[]int
对于i:=0;i
append
是在线性时间(重新分配内存并在每次追加时复制所有内容)还是在摊销的固定时间(就像许多语言中向量类的实现方式一样)?它不会在每次追加时重新分配,并且在:
如果s的容量不够大,无法容纳附加值,append将分配一个新的、足够大的切片,以容纳现有切片元素和附加值。因此,返回的片可能引用不同的底层数组
因此,摊销常数时间就是所问的复杂性。表示,append
内置函数会在必要时重新分配
如果s的容量不足以容纳附加值,
append分配一个新的、足够大的切片,该切片适合
现有切片元素和附加值。因此,该国返回
切片可能引用不同的底层数组
必要时,为追加增加目标切片的精确算法取决于实现。对于当前的gc
编译器算法,请参阅Goruntime
包源文件中的growsice
函数。它是按固定时间摊销的
在某种程度上,切片计算的增长量如下:
newcap := old.cap
doublecap := newcap + newcap
if cap > doublecap {
newcap = cap
} else {
if old.len < 1024 {
newcap = doublecap
} else {
for newcap < cap {
newcap += newcap / 4
}
}
}
输出:
总承包商:
gccgo:
data 3 3 [0 1 2] 2 2 [3 4]
append 8195 9152 2
constant 8195 9152 2
variable 8195 8195 2
总之,根据实现情况,一旦初始容量被填满,append
内置函数可能会也可能不会在每次调用时重新分配
参考资料:
如果s的容量不足以容纳附加值,
append
分配一个新的、足够大的切片,该切片适合
现有切片元素和附加值。因此,该国返回
切片可能引用不同的底层数组
规范(见tip和1.0.3)规定:
“如果s的容量不足以容纳额外的
值,append
分配一个新的、足够大的、适合
现有的slice元素和附加值
返回的切片可能引用不同的基础数组。“
这应该是“如果且仅当”吗?例如,如果我知道
我的切片容量足够长,我能保证吗
是否不更改基础数组
是的,你很放心
运行时源文件
这并不是说“它不会在每个附加上重新分配”。它只是说,如果必要,它会重新分配。@peterSO:Rob Pike,语言作者之一,请求不同意见:不,他没有。我在我的回答中添加了一个附录。@peterSO:“是的,你很有把握。”中的哪个词没有清楚地传达Rob对[邮件列表]OP问题的回答?(这是:“例如,如果我知道我的片的容量足够长,我是否可以保证我不会更改底层数组?”;-)@zzzz,这只是在讨论现有切片足够大的情况。Rob(在这段引文中)完全没有提到在不这样的情况下可以分配多少空间。如果它只是与需要的一样多,那么重新分配就不会被摊销。是的,尽管语言或库引用最好指定它的复杂性,所以用户在编写大型应用程序时可以依赖复杂性。
data 3 3 [0 1 2] 2 2 [3 4]
append 8195 9152 2
constant 8195 9152 2
variable 8195 8195 2
data 3 3 [0 1 2] 2 2 [3 4]
append 8195 9152 2
constant 8195 9152 2
variable 8195 8195 2