scala_cs_210/src/main/scala/quickcheck/Heap.scala
2019-10-30 15:34:26 +01:00

120 lines
3.5 KiB
Scala

package quickcheck
trait IntHeap extends Heap {
override type A = Int
override def ord = scala.math.Ordering.Int
}
// http://www.brics.dk/RS/96/37/BRICS-RS-96-37.pdf
// Figure 1, page 3
trait Heap {
type H // type of a heap
type A // type of an element
def ord: Ordering[A] // ordering on elements
def empty: H // the empty heap
def isEmpty(h: H): Boolean // whether the given heap h is empty
def insert(x: A, h: H): H // the heap resulting from inserting x into h
def meld(h1: H, h2: H): H // the heap resulting from merging h1 and h2
def findMin(h: H): A // a minimum of the heap h
def deleteMin(h: H): H // a heap resulting from deleting a minimum of h
}
// Figure 3, page 7
trait BinomialHeap extends Heap {
type Rank = Int
case class Node(x: A, r: Rank, c: List[Node])
override type H = List[Node]
protected def root(t: Node) = t.x
protected def rank(t: Node) = t.r
protected def link(t1: Node, t2: Node): Node = // t1.r == t2.r
if ord.lteq(t1.x, t2.x) then
Node(t1.x, t1.r + 1, t2 :: t1.c)
else
Node(t2.x, t2.r + 1, t1 :: t2.c)
protected def ins(t: Node, ts: H): H = ts match
case Nil => List(t)
case tp :: ts => // t.r <= tp.r
if t.r < tp.r then
t :: tp :: ts
else
ins(link(t, tp), ts)
override def empty = Nil
override def isEmpty(ts: H) = ts.isEmpty
override def insert(x: A, ts: H) = ins(Node(x, 0, Nil), ts)
override def meld(ts1: H, ts2: H) = (ts1, ts2) match
case (Nil, ts) => ts
case (ts, Nil) => ts
case (t1 :: ts1, t2 :: ts2) =>
if t1.r < t2.r then
t1 :: meld(ts1, t2 :: ts2)
else if t2.r < t1.r then
t2 :: meld(t1 :: ts1, ts2)
else
ins(link(t1, t2), meld(ts1, ts2))
override def findMin(ts: H) = ts match
case Nil => throw new NoSuchElementException("min of empty heap")
case t :: Nil => root(t)
case t :: ts =>
val x = findMin(ts)
if ord.lteq(root(t), x) then
root(t)
else
x
override def deleteMin(ts: H) = ts match
case Nil => throw new NoSuchElementException("delete min of empty heap")
case t :: ts =>
def getMin(t: Node, ts: H): (Node, H) = ts match
case Nil => (t, Nil)
case tp :: tsp =>
val (tq, tsq) = getMin(tp, tsp)
if ord.lteq(root(t), root(tq)) then
(t, ts)
else
(tq, t :: tsq)
val (Node(_, _, c), tsq) = getMin(t, ts)
meld(c.reverse, tsq)
}
trait Bogus1BinomialHeap extends BinomialHeap {
override def findMin(ts: H) = ts match
case Nil => throw new NoSuchElementException("min of empty heap")
case t :: ts => root(t)
}
trait Bogus2BinomialHeap extends BinomialHeap {
override protected def link(t1: Node, t2: Node): Node = // t1.r == t2.r
if !ord.lteq(t1.x, t2.x) then
Node(t1.x, t1.r + 1, t2 :: t1.c)
else
Node(t2.x, t2.r + 1, t1 :: t2.c)
}
trait Bogus3BinomialHeap extends BinomialHeap {
override protected def link(t1: Node, t2: Node): Node = // t1.r == t2.r
if ord.lteq(t1.x, t2.x) then
Node(t1.x, t1.r + 1, t1 :: t1.c)
else
Node(t2.x, t2.r + 1, t2 :: t2.c)
}
trait Bogus4BinomialHeap extends BinomialHeap {
override def deleteMin(ts: H) = ts match
case Nil => throw new NoSuchElementException("delete min of empty heap")
case t :: ts => meld(t.c.reverse, ts)
}
trait Bogus5BinomialHeap extends BinomialHeap {
override def meld(ts1: H, ts2: H) = ts1 match
case Nil => ts2
case t1 :: ts1 => List(Node(t1.x, t1.r, ts1 ++ ts2))
}