記得《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