Я реализовал нижеследующий код слияния. Но я получаю stackOverFlowError в процедуре слияния алгоритма, когда число целых чисел достигает 100000. Я использую сопоставление шаблонов с рекурсией для процедуры слияния. Я понимаю, что использование рекурсии для процедуры слияния не является оптимальным, учитывая, что глубина для этого входа будет достигать 50000. Но поскольку я использую scala, я ожидал некоторой оптимизации компилятора, чтобы сделать рекурсивные вызовы итеративными, поскольку это хвостовые рекурсивные вызовы , Не могли бы вы помочь мне понять, почему я все еще получаю StackOverFlowerror в приведенном ниже коде? Просьба представить информацию о том, как я могу написать это более эффективно в scala? Ниже приведен код:StackOverflowError для mergesort в scala
package common
object Merge {
def main(args: Array[String]) = {
val source = scala.io.Source.fromFile("IntegerArray.txt")
val data = source.getLines.map {line => line.toInt}.toList
println(data.length)
val res = mergeSort(data)
println(res)
}
def mergeSort(data: List[Int]): List[Int] = {
if(data.length <= 1) {data }
else {
val mid = (data.length)/2
val (l, r) = data.splitAt(mid)
val l1 = mergeSort(l)
val l2 = mergeSort(r)
merge(l1, l2)
}
}
def merge(l: List[Int], r: List[Int]): List[Int] = {
l match {
case List() => r
case x::xs => {
r match {
case List() => l
case y::ys => {
if(x<y) {
x :: merge(xs, r)
} else {
y :: merge(l, ys)
}
}
}
}
}
}
}
Ниже исключение я получаю:
Exception in thread "main" java.lang.StackOverflowError
at common.Merge$.merge(Merge.scala:30)
at common.Merge$.merge(Merge.scala:30)
at common.Merge$.merge(Merge.scala:30)
at common.Merge$.merge(Merge.scala:32)
at common.Merge$.merge(Merge.scala:32)
at common.Merge$.merge(Merge.scala:30)
at common.Merge$.merge(Merge.scala:32)
at common.Merge$.merge(Merge.scala:30)
at common.Merge$.merge(Merge.scala:32)
at common.Merge$.merge(Merge.scala:32)
at common.Merge$.merge(Merge.scala:30)
at common.Merge$.merge(Merge.scala:30)
at common.Merge$.merge(Merge.scala:32)
at common.Merge$.merge(Merge.scala:32)
at common.Merge$.merge(Merge.scala:32)
at common.Merge$.merge(Merge.scala:30)
at common.Merge$.merge(Merge.scala:32)
at common.Merge$.merge(Merge.scala:32)
at common.Merge$.merge(Merge.scala:32)
at common.Merge$.merge(Merge.scala:30)
Эх, нет, это не хвостовые рекурсивные вызовы. Хвост вызова - это вызов '::. Apply'. – rightfold
Посмотрите на главный связанный вопрос, как сделать его хвостовым рекурсивом: http://stackoverflow.com/questions/2201472/merge-sort-from-programming-scala-causes-stack-overflow?rq=1 –
Если у вас есть «x :: merge (xs, r)» в методе слияния, это НЕ является хвостовым рекурсивным. Хвост-рекурсивный вызов будет состоять из слияния (a, b) внутри слияния, а не для слияния, являющегося одним из операндов для другой операции. Это не может быть оптимизировано для цикла, оно останется рекурсивным и, возможно, ударит стек, который вы уже испытали. – marekinfo