我正在学习clojure,并希望我的天真快速排序。此实现将数组(向量)减半并以递归方式处理它们。问题是,当递归结束时数组(向量)的大小为1时,此代码会抛出NullPointerException。那是为什么?
(ns qsort)
(defn qsort [arr]
(println "arr" arr)
(def cnt (count arr))
(def pivotidx (if (> cnt 1)
(int (/ cnt 2))
-1
))
(print "pivotidx:" pivotidx " ")
(if (> pivotidx -1)
((def pivotval (nth arr pivotidx))
(println "pivotval:" pivotval " ")
(def right (filter #(> % pivotval ) arr))
(def left (filter #(< % pivotval) arr))
(println "left" left "right" right)
(concat (qsort left) [pivot] (qsort right))
)
arr
)
)
(defn sortme [] (qsort [3 5 8 9 1 7 12 13 2 14 0]))
答案 0 :(得分:4)
其他答案已经很好地描述了“正确”的做事方式,巧合的是也解决了你的问题。但是,您的NPE是由
引起的((def pivotval (nth arr pivotidx))
...more stuff...)
您不能简单地使用()
对元素进行分组:lisp中的(foo)
表示调用函数foo
;同样,((bar) (foo))
表示:
bar
,将结果保存为x
foo
。将结果保存为y
x
y
醇>
因为def
没有返回函数,所以用六个或七个参数调用它的结果会导致问题。
相反,如果您想要分组内容,则应使用do
特殊表单。 (do (foo) (bar))
表示“调用foo,然后返回调用bar的结果”。
答案 1 :(得分:2)
正确使用let代替def是正确的事情:
(defn qsort [arr]
(println "arr" arr)
(let
[
cnt (count arr)
pivotidx (if (> cnt 1) (int (/ cnt 2)) -1)
]
(print "pivotidx:" pivotidx " ")
(if (> pivotidx -1)
(let
[
pivotval (nth arr pivotidx)
right (filter #(> % pivotval ) arr)
left (filter #(< % pivotval) arr)
]
(println "pivotval:" pivotval " ")
(println "left" left "right" right)
(concat (qsort left) [pivotval] (qsort right))
)
arr) ))
然后
(qsort [3 5 8 9 1 7 12 13 2 14 0])
返回:
(0 1 2 3 5 7 8 9 12 13 14)
答案 2 :(得分:1)
(defn qsort
[l]
(cond
(empty? l) '()
:else (let [f (first l)
smaller (filter #(<= % f) (rest l))
bigger (filter #(> % f) (rest l))]
(concat (qsort smaller) [f] (qsort bigger)))))
答案 3 :(得分:0)
如果数组长度为1,则表示如下:
要修复的一些提示/其他错误