Lyt*_*tol 7 recursion functional-programming scala
我正在通过"Scala编程"编写并编写了一个快速实现选择排序算法.但是,由于我在函数式编程方面仍然有点绿色,因此我无法转换为更多Scala-ish风格.对于那里的Scala程序员,我怎样才能使用Lists和vals而不是回到我的命令式方式呢?
Fla*_*gan 10
正如starblue已经说过的那样,你需要一个计算列表最小值的函数,并返回删除了该元素的列表.这是我的尾部递归实现类似的东西(因为我相信foldl在标准库中是尾递归),我试图尽可能地使它尽可能的功能:).它返回一个列表,其中包含原始列表的所有元素(但有些反转 - 参见下面的解释),最小值为head.
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)
}
Run Code Online (Sandbox Code Playgroud)
这基本上是一个折叠,从包含第一个元素的列表开始.xs如果第一个元素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)
}
Run Code Online (Sandbox Code Playgroud)
不幸的是,这个实现不是尾递归的,所以它会炸掉大型列表的堆栈.无论如何,你不应该对大型列表使用O(n ^ 2)排序,但仍然......如果实现是尾递归的话会很好.我会试着想一些......我认为它看起来像是折叠的实现.
尾递归!
为了使它具有尾递归性,我在函数式编程中使用了一种非常常见的模式 - 累加器.它有点落后,因为现在我需要一个被调用的函数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)
}
Run Code Online (Sandbox Code Playgroud)
编辑:更改了答案,将辅助函数作为选择排序函数的子函数.
它基本上将最大值累积到一个列表中,它最终作为基本案例返回.你也可以看到,它是尾递归通过更换accumulator通过throw new NullPointerException-然后检查堆栈跟踪.
这是使用累加器逐步排序.左侧显示列表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
Run Code Online (Sandbox Code Playgroud)
以下显示了逐步折叠以计算最大值:
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
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
3330 次 |
| 最近记录: |