gerade eingeführten Akkumulatoren wächst:
@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
:::
und :+
nehmen O (n) für die Standard-Implementierung List
, so ist es besser, eine geeignetere Sammlung zu verwenden (wie ListBuffer
). Sie können es auch mit foldLeft
anstelle von expliziter Rekursion umschreiben.
Schnellere Option (mit foldLeft
, ohne :+
):
@tailrec
def insert(sorted_xs: List[Int], x: Int, acc: List[Int] = Nil): List[Int] =
if (sorted_xs.nonEmpty) {
val y::ys = sorted_xs
if (x <= y) acc.reverse ::: x :: y :: ys else insert(ys, x, y :: acc)
} else (x :: acc).reverse
scala> List(1,5,3,6,9,6,7).foldLeft(List[Int]())(insert(_, _))
res22: List[Int] = List(1, 3, 5, 6, 6, 7, 9)
Und schließlich mit span
(wie in @ roterl Antwort, aber span
ist ein wenig schneller - es durchläuft Sammlung nur bis > x
gefunden wird):
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)
Dies ist die einzige Lösung, die ich mir vorstellen könnte. Aber dieser Code ist kaum lesbar. Vor allem, wenn Sie es mit der imperativen Alternative vergleichen. Ich frage mich, ob jemand eine elegantere funktionale Lösung kennt. Oder ist dies ein Beweis dafür, dass die Ausdruckskraft der funktionalen Programmierung ihre Grenzen hat? – Dennis
Ich habe foldLeft Option hinzugefügt - sieht gut aus – dk14
Danke. Ihre Foldleft-Ausgabe ist viel expressiver, aber auch viel abstrakter. – eita