Scala中的Union-Find(或Disjoint Set)数据结构

时间:2013-07-01 16:48:15

标签: scala data-structures union-find

我正在寻找Scala中的union-find或disjoint set数据结构的现有实现,然后我尝试自行推送,因为优化看起来有些复杂。

我的意思是this类似的事情 - 优化了两个操作unionfind

有人知道有什么存在吗?我显然试过谷歌搜索。

1 个答案:

答案 0 :(得分:1)

我曾经为自己写过一段时间,我认为这样做得不错。与其他实现不同,findO(1)unionO(log(n))。如果您的union操作比find多,那么这可能不是很有用。我希望你觉得它很有用:

package week2

import scala.collection.immutable.HashSet
import scala.collection.immutable.HashMap
/**
 * Union Find implementaion.
 * Find is O(1)
 * Union is O(log(n))
 * Implementation is using a HashTable. Each wrap has a set which maintains the elements in that wrap.
 * When 2 wraps are union, then both the set's are clubbed. O(log(n)) operation
 * A HashMap is also maintained to find the Wrap associated with each node. O(log(n)) operation in mainitaining it.
 * 
 * If the input array is null at any index, it is ignored
 */
class UnionFind[T](all: Array[T]) {
  private var dataStruc = new HashMap[T, Wrap]
  for (a <- all
  if(a!=null)    
  )
    dataStruc = dataStruc + (a -> new Wrap(a))


    var timeU = 0L
  var timeF = 0L
  /**
   * THe number of Unions
   */
  private var size = dataStruc.size

  /**
   * Unions the set containing a and b
   */
  def union(a: T, b: T): Wrap = {
    val st = System.currentTimeMillis()
    val first: Wrap = dataStruc.get(a).get
    val second: Wrap = dataStruc.get(b).get
    if (first.contains(b) || second.contains(a))
      first
    else {
      //below is to merge smaller with bigger rather than other way around
      val firstIsBig = (first.set.size > second.set.size)
      val ans = if (firstIsBig) {
        first.set = first.set ++ second.set
        second.set.foreach(a => {
          dataStruc = dataStruc - a
          dataStruc = dataStruc + (a -> first)
        })
        first
      } else {
        second.set = second.set ++ first.set
        first.set.foreach(a => {
          dataStruc = dataStruc - a
          dataStruc = dataStruc + (a -> second)
        })
        second
      }
      timeU = timeU + (System.currentTimeMillis() - st)
      size = size - 1
      ans

    }

  }

  /**
   * true if they are in same set. false if not
   */
  def find(a: T, b: T): Boolean = {
    val st = System.currentTimeMillis()
    val ans = dataStruc.get(a).get.contains(b)
    timeF = timeF + (System.currentTimeMillis() - st)
    ans
  }

  def sizeUnion: Int = size

  class Wrap(e: T) {
    var set = new HashSet[T]
    set = set + e

    def add(elem: T) {
      set = set + elem
    }

    def contains(elem: T): Boolean = set.contains(elem)

  }

}