さて、私はScalaを学んでいて、いくつかのアルゴリズムとデータ構造を実装しようとしています。
ベクトルを線形バイナリヒープに変換することを目的としたコードをいくつか作成しました。例えば:
Vector(8,3,4,6,2,5,7,9)
に変換されますVector(9,8,7,6,2,4,5,3)
このように、インデックスが与えられるi
と、その親は次のようになります。(i-1)/2
または奇数またはペアに(i-2)/2
依存します。i
ここにコードを残します。私が探しているのは、実装を改善する方法についてのアドバイスです。または、まったく別の方向で試してみてください。
あなたはこれを次のように使うことができます:new Heap(Vector(8,3,4,6,2,5,7,9))
class Heap(vs: Vector[Int]) {
val heap = build()
private def build():Vector[Int] = {
((1 until vs.length) foldLeft Vector[Int](vs.head)) ( (accu, idx) =>
fixFrom(accu :+ vs(idx), idx) )
}
private def fixFrom(heapToFix:Vector[Int], idx: Int): Vector[Int] = {
val parentIndex = parent(idx)
if(parentIndex == -1 || heapToFix(idx) <= heapToFix(parentIndex)) heapToFix
else {
val nextToFix = (heapToFix.updated(parentIndex, heapToFix(idx))) take idx
val fixed = fixFrom(nextToFix, parentIndex)
val swap = heapToFix.updated(idx, heapToFix(parentIndex))
fixed ++ (swap drop idx)
}
}
def children(parentIndex: Int) =
(valid(2*parentIndex + 1), valid(2*parentIndex + 2))
def parent(childIndex: Int) =
if(childIndex % 2 == 0) valid((childIndex-2)/2)
else valid((childIndex-1)/2)
def valid(idx:Int) =
if(idx >= 0 && idx < vs.length) idx else -1
override def toString = heap mkString " "
}
更新1:以下のアドバイスに従って、いくつかの変更を行いました。
import math.Ordering.Implicits._
class Heap[T: Ordering](vs: Vector[T]) {
val heap = build()
private def build():Vector[T] =
((0 until vs.length) foldLeft Vector.empty[T]) ( (accu, idx) =>
fixUp(accu :+ vs(idx), idx) )
@annotation.tailrec
private def fixUp(h:Vector[T], idx: Int): Vector[T] = {
val parentIdx = parent(idx)
if(parentIdx < 0 || h(idx) <= h(parentIdx)) h
else fixUp(h.updated(parentIdx, h(idx)).updated(idx, h(parentIdx)), parentIdx)
}
def parent(idx: Int) = (idx-1) >> 1
override def toString = heap mkString " "
}