我正致力于实施使用中间评估函数的快速排序;不是测试函数,而是一个估价器,用于替换数字在其他上下文中表示的间接值。
我在所有情况下都无法工作,感觉我已经碰到了一堵砖墙。我的主要目的是按照距离相机的距离对一组中的三角形进行排序(数组是唯一面的索引之一,估值器函数查找给定索引的网格面,然后返回相机的距离) ),但为了简洁起见,我将在下面使用一个更简单的例子。这是Common Lisp中的quicksort- *代码:
(defun quicksort-* (arr lo hi &key (valuator #'identity))
(declare (type (simple-array fixnum (*)) arr)
(type fixnum lo hi)
(type function valuator))
(flet ((%partition (arr p r)
(declare (type (simple-array fixnum (*)) arr)
(type fixnum p r))
(let ((x (funcall valuator (aref arr p)))
(i (1- p))
(j (1+ r)))
(loop do
(loop do
(decf j)
until (<= (funcall valuator (aref arr j)) x))
(loop do
(incf i)
until (>= (funcall valuator (aref arr i)) x))
(if (< i j)
(rotatef (aref arr i) (aref arr j))
(return-from %partition j))))))
(when (< lo hi)
(let ((p (%partition arr lo hi)))
(quicksort arr lo p)
(quicksort arr (1+ p) hi))))
arr)
那究竟会是什么呢?
鉴于
(defparameter *names* #("Earl" "Dudley" "Chuck" "Bob" "Alice"))
和我们想要排序的列表,目前随机加扰为
(defparameter *nameindices* '(2 4 0 1 3))
使用谓词函数&#39; namevaluator&#39;在 nameindices 上运行quicksort- *:
(defun namevaluator (nameindex)
(let ((sortednames (sort (copy-seq *names*) #'string>)))
(position (aref *names* nameindex) sortednames :test #'string=)))
因此应该产生#(4 3 2 1 0)以反映下降排序的名称,对吗?
CL-USER> (quicksort
*nameindices*
0 (1- (length *nameindices*))
:valuator
#'namevaluator)
#(0 1 2 3 4)
嗯,不,不。但是,嘿,至少它仍然排序,即使是相反的。
当然,改变#&#39; string&gt;到#&#39;字符串&lt;在namevaluator函数中应该产生#(4 3 2 1 0)然后,对吗?嗯......不,这就成了答案:
#(1 2 3 4 0)
在%分区函数中翻转&gt; =和&lt; =符号并不会产生更好的结果(并且这可能不是太热的想法);它仍会导致一个结果被排序,另一个结果不按顺序。
我想在%分区中插入一个funcall-predicate测试,它最初只是简单地评估了普通整数值,因为比较只会简单地“工作”。实际上,使用默认的#&#39; IDENTITY函数作为评估器,它确实:
(let ((random-numbers (coerce (loop repeat 30 collect (random 1000)) 'vector)))
(quicksort-* random-numbers 0 (1- (length random-numbers))))
> #(29 91 121 130 191 228 250 382 392 406 443 468 468 480 535 555 576 597 598 604 635 646 646 685 712 721 724 764 849 860)
也许答案就在我的鼻子底下,但我还没有看到它?
答案 0 :(得分:4)
(a)如果递归调用函数,则使用名称quicksort,但函数名称为quicksort- *。我错过了什么吗?
(b)您在顶级调用中传递自定义求值程序,但在递归调用中不这样做,因此对于那些#&#39;身份是有效的。您可以尝试使用标签函数进行递归,这样您就不必重新说明:估价器了。