gpt4 book ai didi

scala - 预置 Scala 向量的复杂性

转载 作者:行者123 更新时间:2023-12-04 18:01:15 25 4
gpt4 key购买 nike

enter image description here

我指的是官方documentation

它将 Vector 的复杂性显示为“有效常数”(eC)。但我的理解是,对于向量,前置意味着还需要调整所有其他索引,这将使操作 O(n) 或 L(线性)。任何人都可以解释如何在向量 eC 中添加(有效地恒定)。

最佳答案

找到以下对 prepend 操作的可视化解释,其中每一步都添加一个字符。为了便于说明,图片仅显示每个块 2 个插槽,但在向量的情况下,每个块将是 32 个插槽。 Vector 维护一个开始索引(或图片中的偏移量)以跟踪空白位置。

enter image description here

以下是来自 Vector.scala 的源代码。由于它不会移动所有元素,因此它不是 O(n)。

override def prepended[B >: A](value: B): Vector[B] = {
if (endIndex != startIndex) {
val blockIndex = (startIndex - 1) & ~31
val lo = (startIndex - 1) & 31

if (startIndex != blockIndex + 32) {
val s = new Vector(startIndex - 1, endIndex, blockIndex)
s.initFrom(this)
s.dirty = dirty
s.gotoPosWritable(focus, blockIndex, focus ^ blockIndex)
s.display0(lo) = value.asInstanceOf[AnyRef]
s
} else {

val freeSpace = (1 << (5 * depth)) - endIndex // free space at the right given the current tree-structure depth
val shift = freeSpace & ~((1 << (5 * (depth - 1))) - 1) // number of elements by which we'll shift right (only move at top level)
val shiftBlocks = freeSpace >>> (5 * (depth - 1)) // number of top-level blocks

if (shift != 0) {
// case A: we can shift right on the top level
if (depth > 1) {
val newBlockIndex = blockIndex + shift
val newFocus = focus + shift

val s = new Vector(startIndex - 1 + shift, endIndex + shift, newBlockIndex)
s.initFrom(this)
s.dirty = dirty
s.shiftTopLevel(0, shiftBlocks) // shift right by n blocks
s.gotoFreshPosWritable(newFocus, newBlockIndex, newFocus ^ newBlockIndex) // maybe create pos; prepare for writing
s.display0(lo) = value.asInstanceOf[AnyRef]
s
} else {
val newBlockIndex = blockIndex + 32
val newFocus = focus

val s = new Vector(startIndex - 1 + shift, endIndex + shift, newBlockIndex)
s.initFrom(this)
s.dirty = dirty
s.shiftTopLevel(0, shiftBlocks) // shift right by n elements
s.gotoPosWritable(newFocus, newBlockIndex, newFocus ^ newBlockIndex) // prepare for writing
s.display0(shift - 1) = value.asInstanceOf[AnyRef]
s
}
} else if (blockIndex < 0) {
// case B: we need to move the whole structure
val move = (1 << (5 * (depth + 1))) - (1 << (5 * depth))
val newBlockIndex = blockIndex + move
val newFocus = focus + move

val s = new Vector(startIndex - 1 + move, endIndex + move, newBlockIndex)
s.initFrom(this)
s.dirty = dirty
s.gotoFreshPosWritable(newFocus, newBlockIndex, newFocus ^ newBlockIndex) // could optimize: we know it will create a whole branch
s.display0(lo) = value.asInstanceOf[AnyRef]
s
} else {
val newBlockIndex = blockIndex
val newFocus = focus

val s = new Vector(startIndex - 1, endIndex, newBlockIndex)
s.initFrom(this)
s.dirty = dirty
s.gotoFreshPosWritable(newFocus, newBlockIndex, newFocus ^ newBlockIndex)
s.display0(lo) = value.asInstanceOf[AnyRef]
s
}
}
} else {
// empty vector, just insert single element at the back
val elems = new Array[AnyRef](32)
elems(31) = value.asInstanceOf[AnyRef]
val s = new Vector(31, 32, 0)
s.depth = 1
s.display0 = elems
s
}
}

关于scala - 预置 Scala 向量的复杂性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49916037/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com