Lisp中的快速排序奇怪的行为?
我设法让我的快速排序函数工作,但我不明白为什么代码的一点小小的更改会导致函数的行为异常。 这是工作代码:Lisp中的快速排序奇怪的行为?,lisp,common-lisp,quicksort,Lisp,Common Lisp,Quicksort,我设法让我的快速排序函数工作,但我不明白为什么代码的一点小小的更改会导致函数的行为异常。 这是工作代码: (defun low (mylist) (setq result (list)) (loop for x in mylist do (if (< x (car mylist)) (setq result (cons x result)))) result) (defun high (mylist) (setq resu
(defun low (mylist)
(setq result (list))
(loop
for x in mylist
do (if (< x (car mylist))
(setq result (cons x result))))
result)
(defun high (mylist)
(setq result (list))
(loop
for x in mylist
do (if (> x (car mylist))
(setq result (cons x result))))
result)
(defun qsort (mylist)
(if (null mylist)
nil
(progn
;(setq l1 (low mylist))
;(setq l2 (high mylist))
(append (qsort (low mylist))
(list (car mylist))
(qsort (high mylist))))))
使用此(qsort(list-354312))
返回(-3112)
我知道预先存储分区是不必要的,但是有没有理由认为这不起作用呢?问题在于您在Common Lisp中使用了错误的变量,而这在大多数实现中都有体现:
CL-USER> (defun low (mylist)
(setq result (list))
(loop for x in mylist do
(if (< x (car mylist))
(setq result (cons x result))))
result)
;Compiler warnings :
; In LOW: Undeclared free variable RESULT
LOW
let
引入新变量,您可以稍后使用setq
运算符分配该变量。例如,这里是qsort
的正确版本:
(defun qsort (mylist)
(if (null mylist)
nil
(let ((l1 (low mylist))
(l2 (high mylist)))
(append (qsort l1) (list (car mylist)) (qsort l2)))))
最后,请注意,您可以用这种方式更简洁、更惯用地编写函数low
(对于high
,也是如此):
正如伦佐所回答的那样,
l1
和l2
是全局变量。如果您通过qsort
的定义跟踪它们的值,则会得到调用(qsort'(-1 4 2 3 0 1))的以下跟踪:
同时,如果使用let
form,跟踪显示:
L1 = NIL L2 = (1 0 3 2 4)
L1 = (0) L2 = (4 2 3)
L1 = NIL L2 = NIL
L1 = (3 2) L2 = NIL
L1 = (2) L2 = NIL
L1 = NIL L2 = NIL
因此,l1
和l2
在递归调用中被分配到更深的NIL
,而在递归调用的顶部,它们的值应该包含非空列表
一般来说,把递归(读函数编程)和赋值混在一起是个坏主意。Renso有答案,但既然你已经使用了循环
,你应该挖掘它的潜力。所以你可以这样做
(取消分区(数字列表轴)
(循环:用于编号:在编号列表中)
:如果(
(defun qsort (mylist)
(if (null mylist)
nil
(let ((l1 (low mylist))
(l2 (high mylist)))
(append (qsort l1) (list (car mylist)) (qsort l2)))))
(defun low (mylist)
(loop for x in mylist
when (< x (car mylist))
collect x))
(defun low (mylist)
(loop for x in (cdr mylist)
when (<= x (car mylist))
collect x))
L1 = NIL L2 = (1 0 3 2 4)
L1 = (0) L2 = (4 2 3)
L1 = NIL L2 = NIL
(-1 0 1)
L1 = NIL L2 = (1 0 3 2 4)
L1 = (0) L2 = (4 2 3)
L1 = NIL L2 = NIL
L1 = (3 2) L2 = NIL
L1 = (2) L2 = NIL
L1 = NIL L2 = NIL