/core/src/main/scala/scalaz/Heap.scala

http://github.com/scalaz/scalaz · Scala · 436 lines · 299 code · 88 blank · 49 comment · 47 complexity · f5d10cf9c7c5936a277337111338c490 MD5 · raw file

  1. package scalaz
  2. import std.tuple._
  3. import EphemeralStream.{EStream, emptyEphemeralStream, ##::}
  4. /**An efficient, asymptotically optimal, implementation of priority queues
  5. * extended with support for efficient size.
  6. *
  7. * The implementation of 'Heap' is based on bootstrapped skew binomial heaps
  8. * as described by:
  9. * G. Brodal and C. Okasaki , "Optimal Purely Functional Priority Queues",
  10. * Journal of Functional Programming 6:839-857 (1996),
  11. *
  12. * Based on the heaps Haskell library by Edward Kmett
  13. */
  14. sealed abstract class Heap[A] {
  15. import Heap._
  16. import Heap.impl._
  17. import Tree._
  18. def fold[B](empty: => B, nonempty: (Int, (A, A) => Boolean, Tree[Ranked[A]]) => B): B
  19. /**Is the heap empty? O(1)*/
  20. def isEmpty: Boolean = fold(true, (_, _, _) => false)
  21. /**Is the heap populated? O(1)*/
  22. final def nonEmpty: Boolean = !isEmpty
  23. /**The number of elements in the heap. O(1)*/
  24. def size: Int = fold(0, (s, _, _) => s)
  25. /**Insert a new value into the heap. O(1)*/
  26. def insert(a: A)(implicit o: Order[A]): Heap[A] = insertWith(o.lessThanOrEqual, a)
  27. /** Alias for insert */
  28. final def +(a: A)(implicit o: Order[A]): Heap[A] = this insert a
  29. def insertAll(as: TraversableOnce[A])(implicit o: Order[A]): Heap[A] =
  30. as.foldLeft(this)((h,a) => h insert a)
  31. def insertAllF[F[_]](as: F[A])(implicit F: Foldable[F], o: Order[A]): Heap[A] =
  32. F.foldLeft(as, this)((h,a) => h insert a)
  33. /**Meld the values from two heaps into one heap. O(1)*/
  34. def union(as: Heap[A]): Heap[A] = (this, as) match {
  35. case (Empty(), q) => q
  36. case (q, Empty()) => q
  37. case (Heap(s1, leq, t1@Node(Ranked(r1, x1), f1)),
  38. Heap(s2, _, t2@Node(Ranked(r2, x2), f2))) =>
  39. if (leq(x1, x2))
  40. Heap(s1 + s2, leq, Node(Ranked(0, x1), skewInsert(leq, t2, f1)))
  41. else
  42. Heap(s1 + s2, leq, Node(Ranked(0, x2), skewInsert(leq, t1, f2)))
  43. }
  44. /**Split the heap into the minimum element and the remainder. O(log n)*/
  45. def uncons: Option[(A, Heap[A])] =
  46. fold(None, (_, _, t) => Some((t.rootLabel.value, deleteMin)))
  47. /**Get the minimum key on the (nonempty) heap. O(1) */
  48. def minimum: A = fold(sys.error("Heap.minimum: empty heap"), (_, _, t) => t.rootLabel.value)
  49. /**Get the minimum key on the (nonempty) heap. O(1) */
  50. def minimumO: Option[A] = fold(None, (_, _, t) => Some(t.rootLabel.value))
  51. /**Delete the minimum key from the heap and return the resulting heap. O(log n) */
  52. def deleteMin: Heap[A] = {
  53. fold(Empty[A], (s, leq, t) => t match {
  54. case Leaf(_) => Empty[A]
  55. case Node(_, f0) => {
  56. val (Node(Ranked(r, x), cf), ts2) = getMin(leq, f0)
  57. val (zs, ts1, f1) : (Forest[A], Forest[A], Forest[A]) = splitForest(r, emptyEphemeralStream, emptyEphemeralStream, cf)
  58. val f2 = skewMeld(leq, skewMeld(leq, ts1, ts2), f1)
  59. val f3 = zs.foldRight(f2)(skewInsert(leq, _, _))
  60. Heap(s - 1, leq, Node(Ranked(0, x), f3))
  61. }
  62. })
  63. }
  64. def adjustMin(f: A => A): Heap[A] = this match {
  65. case Heap(s, leq, Node(Ranked(r, x), xs)) =>
  66. Heap(s, leq, heapify(leq)(Node(Ranked(r, f(x)), xs)))
  67. }
  68. def toUnsortedStream: EStream[A] = fold(emptyEphemeralStream, (_, _, t) => t.flatten.map(_.value))
  69. def toUnsortedList: List[A] = toUnsortedStream.toList
  70. def toUnsortedIList: IList[A] = IList.fromFoldable(toUnsortedStream)
  71. def toEphemeralStream: EStream[A] =
  72. EphemeralStream.unfold(this)(_.uncons)
  73. def toStream: Stream[A] =
  74. Foldable[EphemeralStream].toStream(this.toEphemeralStream)
  75. def toList: List[A] = toStream.toList
  76. def toIList: IList[A] = toEphemeralStream.toIList
  77. /**Map a function over the heap, returning a new heap ordered appropriately. O(n)*/
  78. def map[B: Order](f: A => B): Heap[B] = fold(Empty[B], (_, _, t) => t.foldMap(x => singleton(f(x.value))))
  79. def forall(f: A => Boolean): Boolean = toStream.forall(f)
  80. def exists(f: A => Boolean): Boolean = toStream.exists(f)
  81. def foreach(f: A => Unit): Unit = toStream.foreach(f)
  82. /**Filter the heap, retaining only values that satisfy the predicate. O(n)*/
  83. def filter(p: A => Boolean): Heap[A] =
  84. fold(Empty[A], (_, leq, t) => t foldMap (x => if (p(x.value)) singletonWith(leq, x.value) else Empty[A]))
  85. /**Partition the heap according to a predicate. The first heap contains all elements that
  86. * satisfy the predicate. The second contains all elements that fail the predicate. O(n)*/
  87. def partition(p: A => Boolean): (Heap[A], Heap[A]) =
  88. fold((Empty[A], Empty[A]), (_, leq, t) => t.foldMap(x =>
  89. if (p(x.value)) (singletonWith(leq, x.value), Empty[A])
  90. else
  91. (Empty[A], singletonWith(leq, x.value))))
  92. /**Partition the heap of the elements that are less than, equal to, and greater than a given value. O(n)*/
  93. def split(a: A): (Heap[A], Heap[A], Heap[A]) = {
  94. fold((Empty[A], Empty[A], Empty[A]), (s, leq, t) => {
  95. def f(x: A) : (Heap[A], Heap[A], Heap[A]) = if (leq(x, a)) if (leq(a, x)) (Empty[A], singletonWith(leq, x), Empty[A])
  96. else
  97. (singletonWith(leq, x), Empty[A], Empty[A])
  98. else
  99. (Empty[A], Empty[A], singletonWith(leq, x))
  100. t foldMap (x => f(x.value))
  101. })
  102. }
  103. /**Return a heap consisting of the least n elements of this heap. O(n log n) */
  104. def take(n: Int): Heap[A] = withList(_.take(n))
  105. /**Return a heap consisting of all the members of this heap except for the least n. O(n log n) */
  106. def drop(n: Int): Heap[A] = withList(_.drop(n))
  107. /**Split into two heaps, the first containing the n least elements, the second containing the n
  108. * greatest elements. O(n log n) */
  109. def splitAt(n: Int): (Heap[A], Heap[A]) = splitWithList(_.splitAt(n))
  110. /**Returns a tuple where the first element is a heap consisting of the longest prefix of least elements
  111. * in this heap that do not satisfy the given predicate, and the second element is the remainder
  112. * of the elements. O(n log n) */
  113. def break(p: A => Boolean): (Heap[A], Heap[A]) =
  114. span(x => !p(x))
  115. /**Returns a tuple where the first element is a heap consisting of the longest prefix of least elements
  116. * in this heap that satisfy the given predicate and the second element is the remainder of the elements.
  117. * O(n log n)*/
  118. def span(p: A => Boolean): (Heap[A], Heap[A]) =
  119. splitWithList(_.span(p))
  120. /**Returns a heap consisting of the longest prefix of least elements of this heap that satisfy the predicate.
  121. * O(n log n) */
  122. def takeWhile(p: A => Boolean): Heap[A] =
  123. withList(_.takeWhile(p))
  124. /**Returns a heap consisting of the longest prefix of least elements of this heap that do not
  125. * satisfy the predicate. O(n log n) */
  126. def dropWhile(p: A => Boolean): Heap[A] =
  127. withList(_.dropWhile(p))
  128. /**Remove duplicate entries from the heap. O(n log n)*/
  129. def nub: Heap[A] = fold(Empty[A], (_, leq, t) => {
  130. val x = t.rootLabel.value
  131. val xs = deleteMin
  132. val zs = xs.dropWhile(leq(_, x))
  133. zs.nub.insertWith(leq, x)
  134. })
  135. /**Construct heaps from each element in this heap and union them together into a new heap. O(n)*/
  136. def flatMap[B: Order](f: A => Heap[B]): Heap[B] =
  137. fold(Empty[B], (_, _, t) => t foldMap (x => f(x.value)))
  138. /**Traverse the elements of the heap in sorted order and produce a new heap with applicative effects.
  139. * O(n log n)*/
  140. def traverse[F[_] : Applicative, B: Order](f: A => F[B]): F[Heap[B]] = {
  141. val F = Applicative[F]
  142. F.map(F.traverse(toEphemeralStream)(f))(fromCodata[EStream, B])
  143. }
  144. def foldRight[B](z: B)(f: (A, => B) => B): B = {
  145. Foldable[EStream].foldRight(toEphemeralStream, z)(f)
  146. }
  147. private def withList(f: List[A] => List[A]) = {
  148. import std.list._
  149. fold(Empty[A], (_, leq, _) => fromDataWith(leq, f(toList)))
  150. }
  151. private[scalaz] def insertWith(f: (A, A) => Boolean, x: A) =
  152. fold(singletonWith(f, x), (s, _, t) => {
  153. val y = t.rootLabel.value
  154. if (f(x, y)) Heap(s + 1, f, Node(Ranked(0, x), (t ##:: emptyEphemeralStream)))
  155. else
  156. Heap(s + 1, f, Node(Ranked(0, y),
  157. skewInsert(f, Node(Ranked(0, x), emptyEphemeralStream[Tree[Ranked[A]]]), t.subForest)))
  158. })
  159. private def splitWithList(f: List[A] => (List[A], List[A])) = {
  160. import std.list._
  161. fold((Empty[A], Empty[A]), (_, leq, _) => {
  162. val g = (x: List[A]) => fromDataWith(leq, x)
  163. val x = f(toList)
  164. (g(x._1), g(x._2))
  165. })
  166. }
  167. override def toString = "<heap>"
  168. }
  169. object Heap extends HeapInstances {
  170. final case class Ranked[A](rank: Int, value: A)
  171. type Forest[A] = EStream[Tree[Ranked[A]]]
  172. type ForestZipper[A] = (Forest[A], Forest[A])
  173. /**The empty heap */
  174. object Empty {
  175. def apply[A]: Heap[A] = new Heap[A] {
  176. def fold[B](empty: => B, nonempty: (Int, (A, A) => Boolean, Tree[Ranked[A]]) => B): B = empty
  177. }
  178. def unapply[A](h: Heap[A]): Boolean = h.fold(true, (_, _, _) => false)
  179. }
  180. import Heap.impl._
  181. def fromData[F[_] : Foldable, A: Order](as: F[A]): Heap[A] =
  182. Foldable[F].foldLeft(as, Empty[A])((b, a) => b insert a)
  183. def fromCodata[F[_] : Foldable, A: Order](as: F[A]): Heap[A] =
  184. Foldable[F].foldr(as, Empty[A])(x => y => y insert x)
  185. def fromDataWith[F[_] : Foldable, A](f: (A, A) => Boolean, as: F[A]): Heap[A] =
  186. Foldable[F].foldLeft(as, Empty[A])((x, y) => x.insertWith(f, y))
  187. /**Heap sort */
  188. def sort[F[_] : Foldable, A: Order](xs: F[A]): IList[A] = fromData(xs).toIList
  189. /**Heap sort */
  190. def sortWith[F[_] : Foldable, A](f: (A, A) => Boolean, xs: F[A]): IList[A] = fromDataWith(f, xs).toIList
  191. /**A heap with one element. */
  192. def singleton[A: Order](a: A): Heap[A] = singletonWith[A](Order[A].lessThanOrEqual, a)
  193. /**Create a heap consisting of multiple copies of the same value. O(log n) */
  194. def replicate[A: Order](a: A, i: Int): Heap[A] = {
  195. def f(x: Heap[A], y: Int): Heap[A] =
  196. if (y % 2 == 0) f(x union x, y / 2)
  197. else
  198. if (y == 1) x
  199. else
  200. g(x union x, (y - 1) / 2, x)
  201. def g(x: Heap[A], y: Int, z: Heap[A]): Heap[A] =
  202. if (y % 2 == 0) g(x union x, y / 2, z)
  203. else
  204. if (y == 1) x union z
  205. else
  206. g(x union x, (y - 1) / 2, x union z)
  207. if (i < 0) sys.error("Heap.replicate: negative length")
  208. else
  209. if (i == 0) Empty[A]
  210. else
  211. f(singleton(a), i)
  212. }
  213. def apply[A](sz: Int, leq: (A, A) => Boolean, t: Tree[Ranked[A]]): Heap[A] = new Heap[A] {
  214. def fold[B](empty: => B, nonempty: (Int, (A, A) => Boolean, Tree[Ranked[A]]) => B) =
  215. nonempty(sz, leq, t)
  216. }
  217. def unapply[A](h: Heap[A]): Option[(Int, (A, A) => Boolean, Tree[Ranked[A]])] =
  218. h.fold(None, (sz, leq, t) => Some((sz, leq, t)))
  219. private[scalaz] object impl {
  220. import Tree._
  221. def rightZ[A]: ForestZipper[A] => ForestZipper[A] = {
  222. case (path, x ##:: xs) => (x ##:: path, xs)
  223. }
  224. def adjustZ[A](f: Tree[Ranked[A]] => Tree[Ranked[A]]):
  225. ForestZipper[A] => ForestZipper[A] = {
  226. case (path, x ##:: xs) => (path, f(x) ##:: xs)
  227. case z => z
  228. }
  229. def rezip[A]: ForestZipper[A] => Forest[A] = {
  230. case (s, xs) if s.isEmpty => xs
  231. case (x ##:: path, xs) => rezip((path, x ##:: xs))
  232. }
  233. def rootZ[A]: ForestZipper[A] => A = {
  234. case (_, x ##:: _) => x.rootLabel.value
  235. case _ => sys.error("Heap.rootZ: empty zipper")
  236. }
  237. def zipper[A](xs: Forest[A]): ForestZipper[A] = (emptyEphemeralStream, xs)
  238. def emptyZ[A]: ForestZipper[A] = (emptyEphemeralStream, emptyEphemeralStream)
  239. def minZ[A](f: (A, A) => Boolean): Forest[A] => ForestZipper[A] = {
  240. case s if s.isEmpty => emptyZ
  241. case xs => {
  242. val z = zipper(xs)
  243. minZp(f)(z, z)
  244. }
  245. }
  246. def minZp[A](leq: (A, A) => Boolean):
  247. (ForestZipper[A], ForestZipper[A]) => ForestZipper[A] = {
  248. case (lo, (_, ts)) if ts.isEmpty => lo
  249. case (lo, z) => minZp(leq)(if (leq(rootZ(lo), rootZ(z))) lo else z, rightZ(z))
  250. }
  251. def heapify[A](leq: (A, A) => Boolean): Tree[Ranked[A]] => Tree[Ranked[A]] = {
  252. case n@Node(_, ts) if ts.isEmpty => n
  253. case n@Node(Ranked(r, a), as) => {
  254. val (left, Node(Ranked(rp, ap), asp) ##:: right) = minZ(leq)(as)
  255. if (leq(a, ap)) n
  256. else
  257. Node(Ranked(r, ap), rezip((left, heapify(leq)(Node(Ranked(rp, a), asp)) ##:: right)))
  258. }
  259. }
  260. def singletonWith[A](f: (A, A) => Boolean, a: A) =
  261. Heap(1, f, Node(Ranked(0, a), emptyEphemeralStream[Tree[Ranked[A]]]))
  262. def rank[A](t: Tree[Ranked[A]]) = t.rootLabel.rank
  263. def skewLink[A](f: (A, A) => Boolean,
  264. t0: Tree[Ranked[A]],
  265. t1: Tree[Ranked[A]],
  266. t2: Tree[Ranked[A]]): Tree[Ranked[A]] = (t0, t1, t2) match {
  267. case (Node(Ranked(r0, x0), cf0), Node(Ranked(r1, x1), cf1), Node(Ranked(r2, x2), cf2)) =>
  268. if (f(x1, x0) && f(x1, x2)) Node(Ranked(r1 + 1, x1), t0 ##:: t2 ##:: cf1)
  269. else
  270. if (f(x2, x0) && f(x2, x1)) Node(Ranked(r2 + 1, x2), t0 ##:: t1 ##:: cf2)
  271. else
  272. Node(Ranked(r1 + 1, x0), t1 ##:: t2 ##:: cf0)
  273. }
  274. def link[A](f: (A, A) => Boolean):
  275. (Tree[Ranked[A]], Tree[Ranked[A]]) => Tree[Ranked[A]] = {
  276. case (t1@Node(Ranked(r1, x1), cf1), t2@Node(Ranked(r2, x2), cf2)) =>
  277. if (f(x1, x2)) Node(Ranked(r1 + 1, x1), t2 ##:: cf1)
  278. else
  279. Node(Ranked(r2 + 1, x2), t1 ##:: cf2)
  280. }
  281. def skewInsert[A](f: (A, A) => Boolean, t: Tree[Ranked[A]], ts: Forest[A]): Forest[A] =
  282. ts match {
  283. case t1 ##:: t2 ##:: rest =>
  284. if (rank(t1) == rank(t2))
  285. skewLink(f, t, t1, t2) ##:: rest
  286. else (t ##:: ts)
  287. case _ => t ##:: ts
  288. }
  289. def getMin[A](f: (A, A) => Boolean, trees: Forest[A]): (Tree[Ranked[A]], Forest[A]) =
  290. trees match {
  291. case (t ##:: ts) if ts.isEmpty => (t, emptyEphemeralStream)
  292. case t ##:: ts => {
  293. val (tp, tsp) = getMin(f, ts)
  294. if (f(t.rootLabel.value, tp.rootLabel.value)) (t, ts) else (tp, t ##:: tsp)
  295. }
  296. }
  297. def splitForest[A]:
  298. (Int, Forest[A], Forest[A], Forest[A]) => (Forest[A], Forest[A], Forest[A]) = {
  299. case (0, zs, ts, f) => (zs, ts, f)
  300. case (1, zs, ts, (t ##:: tss)) if tss.isEmpty => (zs, t ##:: ts, emptyEphemeralStream)
  301. case (1, zs, ts, t1 ##:: t2 ##:: f) =>
  302. if (rank(t2) == 0) (t1 ##:: zs, t2 ##:: ts, f)
  303. else
  304. (zs, t1 ##:: ts, t2 ##:: f)
  305. case (r, zs, ts, (t1 ##:: t2 ##:: cf)) =>
  306. if (rank(t1) == rank(t2)) (zs, t1 ##:: t2 ##:: ts, cf)
  307. else
  308. if (rank(t1) == 0) splitForest(r - 1, t1 ##:: zs, t2 ##:: ts, cf)
  309. else
  310. splitForest(r - 1, zs, t1 ##:: ts, t2 ##:: cf)
  311. case (_, _, _, _) => sys.error("Heap.splitForest: invalid arguments")
  312. }
  313. def skewMeld[A](f: (A, A) => Boolean, ts: Forest[A], tsp: Forest[A]) =
  314. unionUniq(f)(uniqify(f)(ts), uniqify(f)(tsp))
  315. def ins[A](f: (A, A) => Boolean, t: Tree[Ranked[A]]): Forest[A] => Forest[A] = {
  316. case s if s.isEmpty => EphemeralStream(t)
  317. case (tp ##:: ts) => if (rank(t) < rank(tp)) t ##:: tp ##:: ts
  318. else
  319. ins(f, link(f)(t, tp))(ts)
  320. }
  321. def uniqify[A](f: (A, A) => Boolean): Forest[A] => Forest[A] = {
  322. case s if s.isEmpty => emptyEphemeralStream
  323. case (t ##:: ts) => ins(f, t)(ts)
  324. }
  325. def unionUniq[A](f: (A, A) => Boolean): (Forest[A], Forest[A]) => Forest[A] = {
  326. case (s, ts) if s.isEmpty => ts
  327. case (ts, s) if s.isEmpty => ts
  328. case (tts1@(t1 ##:: ts1), tts2@(t2 ##:: ts2)) =>
  329. import std.anyVal._
  330. Order[Int].order(rank(t1), rank(t2)) match {
  331. case Ordering.LT => t1 ##:: unionUniq(f)(ts1, tts2)
  332. case Ordering.EQ => ins(f, link(f)(t1, t2))(unionUniq(f)(ts1, ts2))
  333. case Ordering.GT => t2 ##:: unionUniq(f)(tts1, ts2)
  334. }
  335. }
  336. }
  337. }
  338. sealed abstract class HeapInstances {
  339. implicit val heapInstance: Foldable[Heap] = new Foldable[Heap] with Foldable.FromFoldr[Heap] {
  340. def foldRight[A, B](fa: Heap[A], z: => B)(f: (A, => B) => B) = fa.foldRight(z)(f)
  341. }
  342. implicit def heapMonoid[A]: Monoid[Heap[A]] = new Monoid[Heap[A]] {
  343. def append(f1: Heap[A], f2: => Heap[A]) = f1 union f2
  344. def zero = Heap.Empty.apply
  345. }
  346. // implicit def heapEqual[A: Equal]: Equal[Heap[A]] = Equal.equalBy((_: Heap[A]).toStream)
  347. implicit def healEqual[A : Equal](implicit H : Foldable[Heap]): Equal[Heap[A]] = Equal[EStream[A]] contramap {H.toEphemeralStream(_: Heap[A])}
  348. }