English 中文(简体)
职场选择
原标题:Selection sort in functional Scala
  • 时间:2009-11-04 06:54:11
  •  标签:

我通过“Schala方案”来做我的工作,并撰写了快速执行甄选算法的文字。 然而,由于Im在功能性方案规划中仍然只是一个绿灯,我很麻烦地翻译到一个更复杂的情景。 在那里的Schala方案制定者,我如何利用清单和阀,而不是回到我迫切需要的方法?

http://gist.github.com/225870

最佳回答

http://stackoverflow.com/questions/1672074/selection-sort-in-Function-scala/1672190#1672190 您已经说过,需要一种功能,计算一份清单的最低点数,并将清单与删除的内容相重。 这里是我对类似内容的细微重复执行(因为我相信<代码>>、在标准图书馆中是尾歇性的),我试图使其尽可能发挥作用: 这份清单载有原始名单的所有内容(但如有逆转,见下文的解释),至少是头。

def minimum(xs: List[Int]): List[Int] =
  (List(xs.head) /: xs.tail) {
    (ys, x) =>
      if(x < ys.head) (x :: ys)
      else            (ys.head :: x :: ys.tail)
  }

这基本上有两倍,从包含<条码>x>/代码第一要素的清单开始。 如果<编码>xs的第一个要素小于该清单的头目,我们先将其应用于<代码>ys。 否则,我们在清单中添加“编码>ys作为第二个要素。 顺便说一句,我们把我们的名单编为一份新清单,其中载有作为标题的最低限度要素,以及一份包含<条码>xs(不一定按同一顺序排列)所有要素的清单,并作为细节予以删除。 注:这一职能不去除重复。

在创建这一助手职能之后,现在很容易实施选择。

def selectionSort(xs: List[Int]): List[Int] =  
  if(xs.isEmpty) List()
  else {
    val ys = minimum(xs)
    if(ys.tail.isEmpty) 
      ys
    else
      ys.head :: selectionSort(ys.tail)
  }

不幸的是,这一执行是而不是<>/em> 尾歇性的,因此它将打上大名单的顶点。 不管怎么说,你就不使用一种O(n^2)类的大型清单,但是,如果执行是细致的,这还是空洞的。 我试图想一想东西...... 我认为,它将看一看执行。

www.un.org/Depts/DGACM/index_spanish.htm Tail Recursive!

为使这一计划得到恢复,我在职能方案拟订中采用了相当常见的模式,即累积编制。 它是在轨后运行的,因为现在我需要一个称为<代码>maximum的职能,该功能基本上与minimum相同,但最高要素是,其执行准确无误,但使用<代码>>,而不是

def selectionSort(xs: List[Int]) = {
  def selectionSortHelper(xs: List[Int], accumulator: List[Int]): List[Int] =
    if(xs.isEmpty) accumulator
    else {
          val ys = maximum(xs)
          selectionSortHelper(ys.tail, ys.head :: accumulator)
    }

  selectionSortHelper(xs, Nil) 
  }

www.un.org/Depts/DGACM/index_spanish.htm 改变答案,使助手作为甄选职能的一个子功能。

它基本上将最高范围积累到清单中,最终作为基数恢复。 你们还可以看到,通过替换<代码> accumulator,通过<编码>,将新的NllerPointException,对细节进行重复研究,然后检查 st痕。

这里是利用蓄积器逐步分类的一个步骤。 左侧显示名单<代码>xs,右侧显示<代码>accumulator。 在每个步骤中,最高比率都以饥饿表示。

64* 25 12 22 11  ------- Nil
11 22 12 25*     ------- 64
22* 12 11        ------- 25 64
11 12*           ------- 22 25 64
11*              ------- 12 22 25 64
Nil              ------- 11 12 22 25 64

下表显示了计算最高额的分级步骤:

maximum(25 12 64 22 11)

25 :: Nil         /: 12 64 22 11  -- 25 > 12, so it stays as head
25 :: 12          /: 64 22 11     -- same as above
64 :: 25 12       /: 22 11        -- 25 < 64, so the new head is 64
64 :: 22 25 12    /: 11           -- and stays so
64 :: 11 22 25 12 /: Nil          -- until the end

64 11 22 25 12
问题回答

你们应该有在功能风格上进行选择的问题,因为这是一种内部的算法。 从定义上看,是固定的。

你面临的主要问题是,你可以掌握swap的内容。 因此,这一点很重要。 附录一有一份清单(a0 ....../sub> ......>> <>n),其中最低值为x。 您需要获得一份x,然后填写一份清单(0.x-1 ax+1 an)。 问题是,你必然要到copy。 各项要素a0x-1>,如果您希望保持纯功能的话。 其他功能性数据结构,特别是树木,可以比这更好的业绩,但基本问题依然存在。

这里是另一种选择(基因版本)。

def less[T <: Comparable[T]](i: T, j: T) = i.compareTo(j) < 0

def swap[T](xs: Array[T], i: Int, j: Int) { val tmp = xs(i); xs(i) = xs(j); xs(j) = tmp }

def selectiveSort[T <: Comparable[T]](xs: Array[T]) {
    val n = xs.size
    for (i <- 0 until n) {
        val min = List.range(i + 1, n).foldLeft(i)((a, b) => if (less(xs(a), xs(b))) a else b)
        swap(xs, i, min)
    }
  }     

你们需要一种选择的助手职能。 它应将最低要素和清单其余部分移除。

我认为,以功能方式进行选择是合理可行的,但正如丹尼尔指出的,这样做有很好的机会 performing。

我刚刚尝试撰写一份功能性泡沫材料,作为选择的简单易懂的个案。 这里是我做的,也是你可以做的:

define bubble(data)
  if data is empty or just one element: return data;
  otherwise, if the first element < the second,
    return first element :: bubble(rest of data);
    otherwise, return second element :: bubble(
      first element :: (rest of data starting at 3rd element)).

完成学业后,最大的部分在名单末尾。 现在,

define bubblesort [data]
  apply bubble to data as often as there are elements in data.

在这样做的时候,你的数据确实是分类的。 是的,它令人憎恶,但我的衣着执行这一伪装成物。

就第一个要素或两个要素而言,然后将其余部分的工作留给重新开展的活动,就是这样做的有益、实用的方法。 但是,一旦你听从你的思想,就更明智地处理这一问题。

我建议执行《<>>>。

Break list into two sub-lists, 
either by counting off half the elements into one sublist 
  and the rest in the other,
or by copying every other element from the original list 
  into either of the new lists.

Sort each of the two smaller lists (recursion here, obviously).

Assemble a new list by selecting the smaller from the front of either sub-list
until you ve exhausted both sub-lists.

重新入侵处于中间阶段,我看不出使算法尾复发的一条cl路。 然而,我认为,它及时把O(log-2)放在了,并且也把过高的负荷放在了 st上。

Have、好 l!

由于上述情况,他们非常鼓舞人心。 此处采用另一种功能方法处理甄选算法。 我试图把它建立在以下概念之上:通过min(A)=if A=Nil->Int.MaxValue Others min(A.head, min(A.tail),找到一个最大/最小。 第一类是名单的明细,第二类是两个数字。 这是容易理解的,但不幸的是,并非是重复性的。 利用蓄积器方法,可以像现在这样改变狭义的定义:

def min(x: Int,y: Int) = if (x<y) x else y

def min(xs: List[Int], accu: Int): Int = xs match {
    case Nil => accu
    case x :: ys => min(ys, min(accu, x))
}

(即尾歇)

现在需要一个精彩的版本,该版本将一份清单从表面上删除。 下表列出了一份清单,其标题是微不足道的,其详细内容是原始清单的其余部分:

def minl(xs: List[Int]): List[Int] = minl(xs, List(Int.MaxValue))

def minl(xs: List[Int],accu:List[Int]): List[Int] = xs match {
// accu always contains min as head
    case Nil => accu take accu.length-1
    case x :: ys => minl(ys, 
        if (x<accu.head) x::accu else accu.head :: x :: accu.tail )
}

采用这种选择,可以详细进行书面解释,因为:

def ssort(xs: List[Int], accu: List[Int]): List[Int] = minl(xs) match {
    case Nil => accu
    case min :: rest => ssort(rest, min::accu)
}

(推翻命令)。 在10 000个清单要素的测试中,这一算法仅比通常的必要算法低4倍左右。

即便在编码Schala时,Im公司(通过结合器或再行)倾向于采用功能式方案规划(通过变数和变数),而采用必要的风格(通过变数和变数),但就这一具体问题而言,旧的学校必修路导致采用更简单、更干的手法。

我认为,某些类别的问题,如分类算法,通常会改变现有的投入缓冲,而不是产生新的收集方法,不会再回头来。

我的解决办法是:

package bitspoke.algo

import scala.math.Ordered
import scala.collection.mutable.Buffer

abstract class Sorter[T <% Ordered[T]] {

  // algorithm provided by subclasses
  def sort(buffer : Buffer[T]) : Unit

  // check if the buffer is sorted
  def sorted(buffer : Buffer[T]) = buffer.isEmpty || buffer.view.zip(buffer.tail).forall { t => t._2 > t._1 }

  // swap elements in buffer
  def swap(buffer : Buffer[T], i:Int, j:Int) {
    val temp = buffer(i)
    buffer(i) = buffer(j)
    buffer(j) = temp
  }
}


class SelectionSorter[T <% Ordered[T]] extends Sorter[T] {
  def sort(buffer : Buffer[T]) : Unit = {
    for (i <- 0 until buffer.length) {
      var min = i
      for (j <- i until buffer.length) {
        if (buffer(j) < buffer(min))
          min = j
       }
       swap(buffer, i, min)
     }
  }
}

如你所看到的那样,为了实现分辨率多变,而不是使用<代码>java.lang.Comparable,我倾向于scala.math.Ordered<>/code>和 Scala View Bounds,而不是上波兹。 这当然是由于Schala强行将原始类型转换到RichWrappers而取得的。

您可以撰写以下客户方案:

import bitspoke.algo._
import scala.collection.mutable._

val sorter = new SelectionSorter[Int]
val buffer = ArrayBuffer(3, 0, 4, 2, 1)
sorter.sort(buffer)

assert(sorter.sorted(buffer))

在Schala的甄选方案

def selectionSort(list:List[Int]):List[Int] = {
  @tailrec
  def selectSortHelper(list:List[Int], accumList:List[Int] = List[Int]()): List[Int] = {

    list match {
      case Nil => accumList
      case _ => {
        val min  = list.min
        val requiredList = list.filter(_ != min)
        selectSortHelper(requiredList, accumList ::: List.fill(list.length - requiredList.length)(min))
      }
    }
  }
  selectSortHelper(list)
}

你可能想尝试用再行取代你,因此,你有两个地方可以产生新的休养职能。

这将开始消除一些var。

这可能是我最艰难的教训,试图更多地向菲律宾武装部队迈进。

我毫不犹豫地在这里展示解决办法,因为我认为,首先尝试是更好的。

但是,如果可能的话,你应当利用尾矿,以避免在堵塞上出现问题(如果你把一个非常庞大的清单排列)。

这里我的解决办法

def sort(list: List[Int]): List[Int] = {
    @tailrec
    def pivotCompare(p: Int, l: List[Int], accList: List[Int] = List.empty): List[Int] = {
      l match {
        case Nil              => p +: accList
        case x :: xs if p < x => pivotCompare(p, xs, accList :+ x)
        case x :: xs          => pivotCompare(x, xs, accList :+ p)
      }
    }
    @tailrec
    def loop(list: List[Int], accList: List[Int] = List.empty): List[Int] = {
      list match {
        case x :: xs =>
          pivotCompare(x, xs) match {
            case Nil       => accList
            case h :: tail => loop(tail, accList :+ h)
          }
        case Nil => accList
      }
    }

    loop(list)
  }





相关问题
热门标签