快速排序

看了《The Joy of Clojure》的快速排序,觉得比较丑,而且不通用。所以自己又写了一个。不过有一个比不上书里面的。书里面的支持 lazy-seq,而下面这个不支持。可能正是因为要支持 lazy-seq 所以书里面的那个才会那么繁琐吧……

(defn- split-by [pred coll]
[(filter pred coll) (remove pred coll)])

(defn qsort-by [comparator work]
(letfn [(step [ret [pivot & rst :as work]]
(if-not work
ret
(let [[left right] (split-by #(< (comparator % pivot) 0) rst)]
(if (seq left)
(recur ret (concat left [pivot] right))
(recur (conj ret pivot) rst)))))]
(seq (step [] (seq work)))))

(println (qsort-by - [57 66 72 27 16]))
(println (qsort-by - []))
(println (qsort-by - nil))

;=> (16 27 57 66 72)
;=> nil
;=> nil

快速排序(升序)我理解为:给定一个轴(pivot),遍历所有还没有排序完整的元素(rst),把小于轴的元素放到轴的左边(left),把不小于轴的元素放到轴的右边(right)。完全排序好的元素放到结果集(ret)里。如果左边有元素,说明找到了比轴还要小的元素。那么结果集不动,因为还没有找到最小的元素。如果左边没有元素,说明当前的轴就是最小的,把它加入结果集。

split-by 不同于 split-with。split-with 在遇到第一个不满足条件的元素后就终止了。而 split-by 会把整个集合都遍历一遍(这里的实现是遍历了两遍)。

如果需要排序,请用 Clojure 核心库的 sort 函数。这个函数转调 java.util.Arrays.sort 函数,它是经过高度优化的。我的测试表明我的函数比标准库的慢了两三个数量级…… -_-!
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值