Odersky Scala书中的队列实现。第19章
我在关于Scala的Odersky书的第388页上看到了这段代码:Odersky Scala书中的队列实现。第19章,scala,Scala,我在关于Scala的Odersky书的第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]) {
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
实现有问题,而不是第一类
tail
在固定时间内工作,因为elems.tail
是一个固定时间操作(它只返回列表的尾部)。构造函数newslowappendqueue(…)
也是一个常量时间操作,因为它只是包装列表smele
有N>1
元素,那么smele.init
必须从头开始用N-1
元素重新构建一个新列表。这需要线性时间,因此它比第一个队列实现的O(1)
操作慢得多O(N)
操作是有问题的,因为大型N
操作速度较慢,而O(1)
操作基本上从来没有问题O(1)
),追加元素(O(N)
),访问尾部(O(1)
),重建init
(O(N)
)。然后其他一切都变得显而易见
tail
在固定时间内工作,因为elems.tail
是一个固定时间操作(它只返回列表的尾部)。构造函数newslowappendqueue(…)
也是一个常量时间操作,因为它只是包装列表smele
有N>1
元素,那么smele.init
必须从头开始用N-1
元素重新构建一个新列表。这需要线性时间,因此它比第一个队列实现的O(1)
操作慢得多O(N)
操作是有问题的,因为大型N
操作速度较慢,而O(1)
操作基本上从来没有问题O(1)
),追加元素(O(N)
),访问尾部(O(1)
),重建init
(O(N)
)。然后其他一切都变得显而易见
tail
实现需要固定的时间。这是因为由于结构共享,List.tail
是一个固定时间操作,并且将列表包装在新的SlowAppendQueue
中也是一个固定时间操作List
类)的工作方式,第二个head
实现需要固定的时间。每个列表节点后面都有一个指向该节点的链接。要通过init
删除最后一个元素,必须重新生成整个列表List
在开始操作时速度快,但在结束操作时速度慢。另见
tail
实现需要固定的时间。这是因为由于结构共享,List.tail
是一个固定时间操作,并且将列表包装在新的SlowAppendQueue
中也是一个固定时间操作List
类)的工作方式,第二个head
实现需要固定的时间。每个列表节点后面都有一个指向该节点的链接。要通过init
删除最后一个元素,必须重新生成整个列表总之,
List
在开始操作时速度快,但在结束操作时速度慢。另请参见。我相信这只是在Scala中编程FP结构的一个示例。在现实世界中,队列用于绕过线程之间的消息。请参阅JCTools库,以获得不同变体的最佳实现:@andriyplokhotnuk确实这是并发队列的典型用法,但队列也用于许多算法,包括BFS和Dijkstra算法。@BrianMcCutchon Dijkstra算法需要像Fibonacci堆这样的优先级队列,这是一只完全不同的野兽。不幸的是,几十年过去了,在标准库中似乎仍然没有Fibonacci堆(Java和Scala都没有),我相信这只是在Scala中编程FP结构的一个例子。在现实世界中,队列用于绕过线程之间的消息。请参阅JCTools库,以获得不同变体的最佳实现:@andriyplokhotnuk确实这是并发队列的典型用法,但队列也用于许多算法,包括BFS和Dijkstra算法。@BrianMcCutchon Dijkstra算法需要像Fibonacci堆这样的优先级队列,这是一只完全不同的野兽。不幸的是,几十年过去了,在标准库中似乎仍然没有斐波那契堆(无论是在Java中,还是在Scala中)。tail是如何实现的?它不需要遍历整个列表才能到达尾部吗?哦它只是将列表从索引1返回到右后?@Jwan622看一看。函数式编程语言中的单链表自古以来就以这种方式实现。要访问head,只需返回第一个指针。访问tail