尽管在编写 Scala 时,我习惯于更喜欢函数式编程风格(通过组合器或递归)而不是命令式编程风格(通过变量和迭代),这一次,对于这个特定问题,老派的命令式嵌套循环导致更简单的代码读者。对于某些类型的问题(例如排序算法,它通常会改变作为输入传递的项目缓冲区,而不是产生新的排序集合),我不认为回退到命令式样式是错误的
这是我的解决方案:
package bitspoke.algo
import scala.math.Ordered
import scala.collection.mutable.Buffer
abstract class Sorter[T <% Ordered[T]] {
// algorithm provided by subclasses
def sort(buffer : Buffer[T]) : Unit
// check if the buffer is sorted
def sorted(buffer : Buffer[T]) = buffer.isEmpty || buffer.view.zip(buffer.tail).forall { t => t._2 > t._1 }
// swap elements in buffer
def swap(buffer : Buffer[T], i:Int, j:Int) {
val temp = buffer(i)
buffer(i) = buffer(j)
buffer(j) = temp
}
}
class InsertionSorter[T <% Ordered[T]] extends Sorter[T] {
def sort(buffer : Buffer[T]) : Unit = {
for {
i <- 1 until buffer.length
j <- i until 0 by -1
if (buffer(j) < buffer(j - 1))
}
swap(buffer, j, j - 1)
}
}
如您所见,java.lang.Comparable
我更喜欢scala.math.Ordered
Scala View Bounds 而不是Upper Bounds,而不是使用。这肯定是有效的,这要归功于原始类型到丰富包装器的许多 Scala 隐式转换。
您可以编写一个客户端程序,如下所示:
import bitspoke.algo._
import scala.collection.mutable._
val sorter = new InsertionSorter[Int]
val buffer = ArrayBuffer(3, 0, 4, 2, 1)
sorter.sort(buffer)
assert(sorter.sorted(buffer))