Scala 如何将函数插入排序代码更改为尾部递归
最近我用函数式编程风格实现了insert_排序算法,它变得更加简洁和声明性。问题是如何将其更改为尾部递归,如果列表的大小增加到10000,代码将抛出异常Scala 如何将函数插入排序代码更改为尾部递归,scala,recursion,tail-recursion,insertion-sort,Scala,Recursion,Tail Recursion,Insertion Sort,最近我用函数式编程风格实现了insert_排序算法,它变得更加简洁和声明性。问题是如何将其更改为尾部递归,如果列表的大小增加到10000,代码将抛出异常 def InsertSort(xs: List[Int]): List[Int] = xs match { case Nil => Nil case x::rest => def insert (x: Int, sorted_xs:List[Int]) :List[Int] = sorted_xs m
def InsertSort(xs: List[Int]): List[Int] = xs match {
case Nil => Nil
case x::rest =>
def insert (x: Int, sorted_xs:List[Int]) :List[Int] = sorted_xs match{
case Nil => List(x)
case y::ys => if (x <= y) x::y::ys else y::insert(x,ys)
}
insert(x,InsertSort(rest))
}
def InsertSort(xs:List[Int]):List[Int]=xs匹配{
案例Nil=>Nil
案例x::rest=>
def insert(x:Int,排序的xs:List[Int]):List[Int]=排序的xs匹配{
案例Nil=>List(x)
案例y::ys=>如果(x刚刚引入了蓄能器:
@tailrec def InsertSort(xs: List[Int], acc: List[Int] = Nil): List[Int] =
if (xs.nonEmpty) {
val x :: rest = xs
@tailrec
def insert(x: Int, sorted_xs: List[Int], acc: List[Int] = Nil): List[Int] =
if (sorted_xs.nonEmpty) {
val y :: ys = sorted_xs
if (x <= y) acc ::: x :: y :: ys else insert(x,ys, acc :+ y)
} else acc ::: List(x)
InsertSort(rest, insert(x, acc))
} else acc
最后使用span
(就像@roterl的回答一样,但是span
要快一点-它只在找到>x
之前遍历集合):
def insert(sortedxs:List[Int],x:Int)=if(sortedxs.nonEmpty){
val(更小,更大)=排序的_x.span(xList(1,5,3,6,9,6,7).foldLeft(List[Int]())(插入)
res25:List[Int]=List(1,3,5,6,6,7,9)
要使其尾部递归,应将排序列表作为参数传递,而不是在返回值处构建:
def InsertSort(xs: List[Int]): List[Int] = {
@tailrec
def doSort(unsortXs: List[Int], sorted_xs: List[Int]): List[Int] = {
unsortXs match {
case Nil => sorted_xs
case x::rest =>
val (smaller, larger) = sorted_xs.partition(_ < x)
doSort(rest, smaller ::: x :: larger)
}
}
doSort(xs, List())
}
def InsertSort(xs:List[Int]):List[Int]={
@泰勒克
def doSort(unsortXs:List[Int],sortedxs:List[Int]):List[Int]={
反排序匹配{
案例Nil=>sorted_xs
案例x::rest=>
val(较小,较大)=已排序的分区(x
这是我能想到的唯一解决方案。但这段代码几乎不可读。特别是如果你将其与命令式解决方案进行比较。我想知道是否有人知道更优雅的函数式解决方案。或者这是函数式编程的表达能力有其局限性的证据?我添加了foldLeft选项-看起来很漂亮谢谢。你的foldleft版本更具表现力,但也更具抽象性。'partition'只是取代了这里的Insert方法。@dk14的答案更完整。
def insert(sorted_xs: List[Int], x: Int) = if (sorted_xs.nonEmpty) {
val (smaller, larger) = sorted_xs.span(_ < x)
smaller ::: x :: larger
} else x :: Nil
scala> List(1,5,3,6,9,6,7).foldLeft(List[Int]())(insert)
res25: List[Int] = List(1, 3, 5, 6, 6, 7, 9)
def InsertSort(xs: List[Int]): List[Int] = {
@tailrec
def doSort(unsortXs: List[Int], sorted_xs: List[Int]): List[Int] = {
unsortXs match {
case Nil => sorted_xs
case x::rest =>
val (smaller, larger) = sorted_xs.partition(_ < x)
doSort(rest, smaller ::: x :: larger)
}
}
doSort(xs, List())
}