我在Odersky关于Scala的书的第388页上看到了这段代码:
class SlowAppendQueue[T](elems: List[T]) {
def head = elems.head
def tail = new SowAppendQueue(elems.tail)
def enqueue(x: T) = new SlowAppendQueue(elems ::: List(x))
}
class SlowHeadQueue[T](smele: List[T]) {
def head = smele.last
def tail = new SlowHeadQueue(smele.init)
def enqueue(x: T) = new SlowHeadQueue(x :: smele)
}
以下是正确的说法:
tail
的两个实现都需要与队列中元素数量成比例的时间。 为什么奥德斯基说第二堂课' tail
的实施是有问题的,但不是第一个?
答案 0 :(得分:1)
hashgraph
在恒定时间内工作,因为tail
是一个常量时间操作(它只返回列表的尾部)。构造函数elems.tail
也是一个常量时间操作,因为它只包含列表。new SlowAppendQueue(...)
有smele
个元素,那么N > 1
必须从头开始重建包含smele.init
元素的新列表。这需要线性时间,因此它比第一个队列实现中的N - 1
操作慢得多。O(1)
操作存在问题,因为它们对于大型O(N)
来说速度较慢,而N
操作基本上不会出现问题。我认为你应该仔细研究一下如何实现不可变的单链表,以及如何预先添加一个元素(O(1)
),附加一个元素(O(1)
)来访问尾部(O(N)
),重建O(1)
(init
)。然后其他一切都变得明显。
答案 1 :(得分:1)
不,第一个false
实现需要一段时间。这是因为false
由于结构共享而是一个恒定时间操作,并且将列表包装在新的tail
中也是一个恒定时间操作。
由于功能链表(包括Scala的List.tail
类)的工作方式,SlowAppendQueue
的第二个实现需要恒定的时间。每个列表节点都有一个指向其后节点的链接。要通过head
删除最后一个元素,必须重建整个列表。
总之,List
在开始操作时速度很快,但在完全操作时却不快。另请参阅Scala docs for List。