的我看到了「編程在斯卡拉」第24章「深度集合」這個例子。這個例子顯示了兩種可選的方式來實現一棵樹:級聯迭代
通過延長
Traversable[Int]
- 這裏的def foreach[U](f: Int => U): Unit
複雜性將是O(N)
。通過延伸
Iterable[Int]
- 在這裏複雜的def iterator: Iterator[Int]
將是O(N log(N))
。
這是爲了證明爲什麼它會是有幫助的兩個獨立的特質,Traversable
和Iterable
。
sealed abstract class Tree
case class Branch(left: Tree, right: Tree) extends Tree
case class Node(elem: Int) extends Tree
sealed abstract class Tree extends Traversable[Int] {
def foreach[U](f: Int => U) = this match {
case Node(elem) => f(elem)
case Branch(l, r) => l foreach f; r foreach f
}
}
sealed abstract class Tree extends Iterable[Int] {
def iterator: Iterator[Int] = this match {
case Node(elem) => Iterator.single(elem)
case Branch(l, r) => l.iterator ++ r.iterator
}
}
關於foreach
實施他們說:
遍歷平衡樹需要的時間與樹 元素的數量。要看到這一點,考慮到對於平衡樹 與
N
葉,你將有N - 1
類Branch的內部節點。因此, 遍歷樹的步驟總數爲N + N - 1
。
這是有道理的。 :)
然而,他們提到在iterator
方法的兩個迭代的級聯有時間的log(N)
複雜,因此該方法的總的複雜性將是N log(N)
:
元件被產生每次通過級聯迭代器(如
l.iterator ++ r.iterator
),計算需要間接地沿着一個 以得到右迭代器(l.iterator
或r.iterator
)。總體而言,這使得log(N)
間接尋找具有N片樹葉的平衡樹的葉子 。因此,即使瀏覽樹中的所有元素的成本約2N
的foreach
遍歷方法走到N log(N)
與iterator
遍歷。
????
爲什麼的級聯迭代需要計算得到的左側或右側迭代器的葉子?
不知道我理解你的問題。連接的迭代器需要在每個**元素(葉)下面「獲取」**。任何特定的葉子將由'l.iterator'或'r.iterator'提供。如果樹是平衡的,那麼遍歷到樹葉的間接指向數就是樹的深度。因此,對於N個葉子,log(N)遍歷以獲得任何特定的葉子。 – jwvh
@jwvh更新了我的問題。正如你所看到的,'foreach'方法也會訪問每一片葉子。但總的複雜性只有O(N)。雖然'iterator'的複雜性是'O(N log(N))'。顯然,在'iterator'上應用'++'會增加複雜性。 – rapt