(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 函数,它是经过高度优化的。我的测试表明我的函数比标准库的慢了两三个数量级…… -_-!
4 条评论:
你好,我最近也开始对clojure感兴趣,一直想看The Joy of Clojure,可是我一直找不到,不知道你是否介意发给我一份它的pdf。另外,很想认识你跟你讨教clojure及其他方面的编程问题。
QQ:566391,msn:liumengjiang@msn.com。
没有问题,虽然这么做不好,但是外国书真的很贵……
这本书前两周刚好所有章节都出完了,现在还有排版问题和错误,不过文本和例子不会再变动了。考虑到你可以看到我的博客,说明你在墙外,有钱的话还请到 manning 的官网买个电子版,很快的,大概 120 块人民币。等到正式版出来了他们还会再给你新的下载。
另外,如果是新学,建议先看《Programming Clojure》,比这本书系统。然后再看 Clojure 的 core.clj,把核心库看懂对于理解的帮助大到无法想象,至少我个人这么觉得。最后才是看这本书。因为这本书里面涉及到的东西非常杂。也正因为如此才有趣味~~~
120元不是问题,但是我不知道怎么用人民币支付,希望能认识你。
前天我就加你msn了,你一直没上过线
发表评论