Quick Union功能风格

时间:2017-07-07 20:28:00

标签: algorithm scala functional-programming sbt

我试图通过实施Sedgewick和Wayne的“算法的第4版”(scala)(以及我的技术诀窍,功能风格)练习,将学习与乐趣混合在一起。

在练习1.5.7我阻止并希望有人可以帮助我。所以任务是编写QuickUnion实现。您可以找到Java implementation here

我已经编写了我的scala版本,它似乎有意义,但控制台输出完全令人沮丧。我正在创建一个包含625个初始组件的数组,但是......最后的组件数量是......零以下

不用多说这是我的实施:

<h4>3. Scouting for a location</h4>

abstract classunderlying trait都在我的github存储库中。为了便于阅读,我正在Main类下面复制:

package ca.vgorcinschi.algorithms1_5_7.quickUnionUF

import scala.concurrent.Future
import scala.concurrent.ExecutionContext.Implicits.global

class QuickUnionUF(size: Int) extends AbstractUF(size) {

  override val array = (0 to size).toArray

  override def find(p: Int): Int = {
    validate(p)
    Stream.iterate(p)(p => array(p)).dropWhile { _ != array(p) }.head
  }

  override def connected(p: Int, q: Int): Boolean = find(p) == find(q)

  override def union(p: Int, q: Int) = {
    /*
     * need to declare Futures outisde
     * for-comprehension loop to run in parallel
     */
    val fRootP = Future { find(p) }
    val fRootQ = Future { find(q) }

    for {
      rootP <- fRootP
      rootQ <- fRootQ
      if (rootP != rootQ)
    } {
      array(rootP) = rootQ
      count -= 1
    }
  }

}

此外,这些是运行输出的第一行和最后一行:

import scala.io.Source
import ca.vgorcinschi.algorithms1_5_7.quickUnionUF.QuickUnionUF
import scala.util.matching.Regex

object Main extends App {
  val allLines = Source.fromFile("src/main/resources/mediumUF.txt").getLines().toList
  //get & print the initial number of components
  val size = allLines.head.trim.toInt
  println(s"Le nombre initial de composants est $size")

  val uf = new QuickUnionUF(size)

  val Integer = new Regex("(-)?(\\d+)")

  for (line <- allLines.tail) {
    val p = Integer findFirstIn line

    assert(p.isDefined)

    val intP = p.get toInt
    val q = Integer findFirstIn line.substring(p.get.length).replace("\\s+", "")

    assert(q.isDefined)

    val intQ = q.get.toInt
    if (!uf.connected(intP, intQ)) {
      uf.union(intP, intQ)
      println(s"L`union fait sur $intP et $intQ")
      println(s"Le nombre des composants est maintenant - ${uf.counter()}")
    }
  }
}

我确实害怕鞋子在我的未来或基于流的查找中捏,但我似乎无法弄明白......

1 个答案:

答案 0 :(得分:0)

我想我明白了。解决方案很奇怪,因为它让我想知道原始解决方案是如何工作的。基本上我只是重写了父类中的counter()来返回array.distinct.length,即不同的整数或根:

/*
 * takes the initial number of components
 * as its argument
 */
abstract class AbstractUF(var count: Int) extends UF{

  override def counter() = array.distinct.length

  val array: Array[Int]

...
}

输出:

Le nombre initial de composants est 625
L`union fait sur 528 et 503
Le nombre des composants est maintenant - 625
L`union fait sur 548 et 523
Le nombre des composants est maintenant - 624
L`union fait sur 389 et 414
Le nombre des composants est maintenant - 623
L`union fait sur 446 et 421
Le nombre des composants est maintenant - 622
L`union fait sur 552 et 553
Le nombre des composants est maintenant - 621
L`union fait sur 154 et 155
Le nombre des composants est maintenant - 620
...
Le nombre des composants est maintenant - 266
L`union fait sur 295 et 320
Le nombre des composants est maintenant - 266
L`union fait sur 160 et 159
Le nombre des composants est maintenant - 266
L`union fait sur 463 et 464
Le nombre des composants est maintenant - 266
L`union fait sur 10 et 35
Le nombre des composants est maintenant - 266
L`union fait sur 619 et 594
Le nombre des composants est maintenant - 265
L`union fait sur 403 et 402
Le nombre des composants est maintenant - 265