120 lines
3.5 KiB
Scala
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))
|
|
}
|