我在scala 2.11.8版本中编写合并排序程序。
以下是我的计划 -
object ListMergeSort {
def main(args:Array[String]): Unit ={
val list:List[Int]= List(1,5,7,2,9,3,8,6,4)
println(list)
println(sort(list))
}
def sort(l:List[Int]):List[Int]= {
l match{
case Nil => l
case h::Nil => l
case _ =>
val (l1,l2) = l splitAt(l.length/2)
listMergeSort(sort(l1),sort(l2))
}
}
//@annotation.tailrec
def listMergeSort(l1:List[Int],l2:List[Int]):List[Int]={
(l1,l2) match{
case (Nil,l2) => l2
case (l1,Nil) => l1
case (h1::t1, h2::t2) => if (h1<h2) h1::listMergeSort(t1,l2) else h2::listMergeSort(l1,t2)
}
}
}
上述程序在技术上工作正常,输出为我提供了排序列表。
我想将listMergeSort函数注释为尾递归,但编译器给出错误“递归调用不在尾部位置”。
import scala.util.Random
object test {
def msort[T <% Ordered[T]](xs: List[T]): List[T] = {
@annotation.tailrec
def merge(res: List[T], xs: List[T], ys: List[T]): List[T] = (xs, ys) match {
case (_, Nil) => res.reverse ::: xs
case (Nil, _) => res.reverse ::: ys
case (x :: xs1, y :: ys1) =>
if (x < y) merge(x :: res, xs1, ys)
else merge(y :: res, xs, ys1)
}
val n = xs.length / 2
if (n == 0) xs
else {
val (ys, zs) = xs splitAt n
merge(Nil, msort(ys), msort(zs))
}
}
def main(args: Array[String]) {
val list = Seq.fill(10)(Random.nextInt(500)).toList
println(list)
println(msort(list))
}
}
上述程序也有类似的合并功能,但@ annotation.tailrec没有抛出任何错误。
任何人都可以帮助我的程序中出现错误的根本原因吗?
答案 0 :(得分:4)
编译器告诉你要告诉你的一切。
这一行..
if (h1<h2) h1::listMergeSort(t1,l2) else h2::listMergeSort(l1,t2)
...不是尾递归,因为在 listMergeSort()
之后返回还有更多工作要做,即预先挂起h1
或h2
元素。
另一方面,这一行是是尾递归...
if (x < y) merge(x :: res, xs1, ys) else merge(y :: res, xs, ys1)
...因为在merge
返回后没有其他任何事情可做,只需返回merge()
返回的内容。