记得《Function Thinking》这本书中提到,如今的编程范式有两类,一类是“命令式编程”,另外一类是“函数式编程”,如今咱们最常使用的许多语言像c、c++、java都是命令式的,但其中c++和java也都有一些函数式的类库,可见函数式特性仍是受一些程序员的青睐的。还有一些纯函数式的语言如 clojure、haskell则彻底是纯函数式的。像python、scala则是混合型的,包含两种范式,给程序员提供了巨大的灵活性,使解决问题的方式更多,可谓是程序员的一大利器。
如今就以scala语言的"pattern matching"来实现一些经典的排序算法,来展现一下函数式编程思惟方式上带给咱们的惊喜和享受。java
经过相邻元素比较交换的方式,将最大的元素依次移动到列表中未排好序部分的尾部,重复操做,直到列表中未排好序的部分为空,从而使整个列表有序python
经过相邻元素比较交换的方式,将最大的元素依次移动到列表中未排好序部分的尾部,重复操做,直到列表中未排好序的部分为空,从而使整个列表有序c++
object BubbleSort { /** * @param list 待排序列表 * @tparam A 列表元素类型 * @return */ def bubbleSort[A <% Ordered[A]](list: List[A]): List[A] = { /** * @param unSorteds 每一趟冒泡时待排序列表 * @param remains 已遍历且未冒出的元素列表 * @param accOrdereds 已冒出的元素组成的有序列表(是累积的) * @return 每一趟冒泡后排好序的列表 */ @tailrec def bubble(unSorteds: List[A], remains: List[A], accOrdereds: List[A]): List[A] = unSorteds match { case h1 :: h2 :: t => if (h1 > h2) bubble(h1 :: t, h2 :: remains, accOrdereds) else bubble(h2 :: t, h1 :: remains, accOrdereds) case h1 :: Nil => if (remains.isEmpty) return h1 :: accOrdereds else bubble(remains, Nil,h1 :: accOrdereds) } bubble(list, Nil, Nil) } def main(args: Array[String]): Unit = { val list = List(1,13,7,5,8,9,20,43,11,8) println(bubbleSort(list)) } }
使用分治思想,将数列用选好的基准点划分为两个子序列(也就是将比基准点小的元素放左边,比基准点大的元素放右边),递归对子序列使用此方法进行此操做,递归到最底部时,数列的大小是零或一,也就是已排好序。程序员
利用scala的模式匹配对序列进行匹配,分两种状况:算法
object QuickSort extends App { /** * 快速排序 * * @param list 待排序列表 * @tparam A 列表元素类型 * @return */ def quickSort[A <% Ordered[A]](list: List[A]): List[A] = list match { case Nil => List() case head :: tail => val (left, right) = tail.partition(_ < head) quickSort(left) ::: head :: quickSort(right) } val list = List(1, 13, 7, 5, 8, 9, 20, 43, 11, 8) println(quickSort(list)) }
经过构建有序序列,对于未排序数据,在已排序序列中从后向前扫描,找到相应位置并插入,直到将全部未排序数据都插入到已排序序列中,排序便完成编程
注意
scala中List的头(head)是List中第一个元素,List的尾(tail)是去掉头元素(head)后的List函数式编程
object InsertionSort extends App { /** * @param list 待排列表 * @tparam A 列表元素类型 * @return */ def insertionSort[A <% Ordered[A]](list: List[A]): List[A] = { /** * @param unSorteds 待排列表 * @param accOrdereds 累积有序列表 * @return 有序列表 */ @tailrec def sort(unSorteds: List[A], accOrdereds: List[A]): List[A] = unSorteds match { case ha :: ta => sort(ta, insert(ha, accOrdereds)) case Nil => accOrdereds } /** * @param a 待插入元素 * @param accOrdereds 累积有序列表 * @return */ def insert(a: A, accOrdereds: List[A]): List[A] = accOrdereds match { case h :: t if (a > h) => h :: insert(a, t) case _ => a :: accOrdereds } sort(list, Nil) } val list = List(1,13,7,5,8,9,20,43,11,8) println(insertionSort(list).mkString(",")) }
使用分治思想,将序列划分为若干个只有一个元素的子序列,重复进行merge排序操做,将子序列两两合并,直到最后只剩下一个子序列,这个子序列就是已排好的序列函数
object MergeSort extends App { def mergeSort[A <% Ordered[A]](list: List[A]): List[A] = { /** * @param p 待排序的包含两个列表的元组 * @return */ def sort(p: (List[A], List[A])): List[A] = { p match { case (Nil, Nil) => Nil case (a :: Nil, Nil) => a :: Nil case (Nil, a :: Nil) => a :: Nil case (as, bs) => merge(splitIn2AndSort(as), splitIn2AndSort(bs)) } } /** * 将给定列表划分为两个列表,并归并排序返回一个有序列表 * @param as 待划分列表 * @return */ def splitIn2AndSort(as: List[A]): List[A] = sort(splitIn2(as)) /** * 合并两个有序列表 * @param as 有序列表 * @param bs 有序列表 * @return 合并后的有序列表 */ def merge(as: List[A], bs: List[A]): List[A] = { def loop(cs: List[A], ds: List[A], accSorteds: List[A]): List[A] = (cs, ds) match { case (Nil, Nil) => accSorteds case (hc :: tc, hd :: td) => if (hc < hd) loop(tc, ds, hc :: accSorteds) else loop(td, cs, hd :: accSorteds) case (hc :: tc, Nil) => loop(tc, Nil, hc :: accSorteds) case (Nil, hd :: td) => loop(Nil, td, hd :: accSorteds) } loop(as, bs, Nil).reverse } def splitIn2(as: List[A]): (List[A], List[A]) = { val mid = as.length / 2 (as.slice(0, mid), as.slice(mid, as.length)) } splitIn2AndSort(list) } val list = List(1, 13, 7, 5, 8, 9, 20, 43, 11, 8) println(mergeSort(list).mkString(",")) }
从原序列中依次移出符合条件(最大或最小)的元素,放入到有序序列中,直到原序列吴待排序元素oop
object SelectionSort extends App { def selectionSort[A <% Ordered[A]](list: List[A]): List[A] = { /** * @param unSorteds 未排序列表 * @param accSorteds 累积最终的有序列表 * @return */ def sort(unSorteds: List[A], accSorteds: List[A]): List[A] = unSorteds match { case h :: t => select(unSorteds, Nil, accSorteds) case Nil => accSorteds } /** * * @param unSorteds 未排序列表 * @param sorteds 选择出的元素组成的有序列表 * @param accSorteds 累积最终的有序列表 * @return */ @tailrec def select(unSorteds: List[A], sorteds: List[A], accSorteds: List[A]): List[A] = unSorteds match { case h1 :: h2 :: t => if (h1 < h2) select(h2 :: t, h1 :: sorteds, accSorteds) else select(h1 :: t, h2 :: sorteds, accSorteds) case h :: Nil => sort(sorteds, h :: accSorteds) case Nil => sort(sorteds, accSorteds) } sort(list, Nil) } val list = List(1, 13, 7, 5, 8, 9, 20, 43, 11, 8) println(selectionSort(list)) }
以上五种排序算均采用scala函数式方式实现,实现过程多采用递归思惟和模式匹配,这也是函数式编程一般使用的方式。ui