Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/303.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Lisp中的快速排序奇怪的行为?_Lisp_Common Lisp_Quicksort - Fatal编程技术网

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