lisp中的Quicksort显示lambda函数错误

时间:2015-09-27 17:59:24

标签: common-lisp quicksort clisp

我为quicksort编写了以下代码,与C代码非常相似。但是在这里它只读取list的元素。之后它说分区函数应该是lambda函数。我是lisp的新手。请帮帮我。我的代码是: -

{{1}}

想知道这个lambda函数是什么。它只是一个给定一个尚未定义的函数的匿名名称

2 个答案:

答案 0 :(得分:5)

我会一步一步地这样做。首先,使用标准格式:

(print "Enter the elements of the array")
(setq k 10)
(setq A (make-array '(10)))
(setq i 0)
(loop
  (if (>= i 10) (return))
  (setq x (read))
  (setf (aref A i) x)
  (incf i))

(defun quicksort (start end)
  (if (< start end)
      ((setq pindex (lambda (start end)))
       (quicksort(start (- pindex 1)))
       (quicksort((+ pindex 1) end)))))

(defun partition (start end)
  (setq pivot (aref A end))
  (setq pindex start)
  (setq j 0)
  (loop
    (if (>= j end) return)
    (if (< (aref A j) pivot)
        ((setq temp (aref A pindex))
         (setq pindex (aref A j))
         (setq (aref A j) temp)
         (incf pindex)))
    (incf j))
  (setq temp (aref A pindex))
  (setq (aref A pindex) pivot)
  (setq (aref A end) temp))

(quicksort 0 10)

说出当前的问题:括号总是包围表格,但它们没有 小组形式本身。

(print "Enter the elements of the array")
(setq k 10)
(setq A (make-array '(10)))
(setq i 0)
(loop
  (if (>= i 10) (return))
  (setq x (read))
  (setf (aref A i) x)
  (incf i))

(defun quicksort (start end)
  (if (< start end)
      (progn
        (setq pindex (lambda (start end)))
        (quicksort(start (- pindex 1)))
        (quicksort((+ pindex 1) end)))))

(defun partition (start end)
  (setq pivot (aref A end))
  (setq pindex start)
  (setq j 0)
  (loop
    (if (>= j end) return)
    (if (< (aref A j) pivot)
        (progn
          (setq temp (aref A pindex))
          (setq pindex (aref A j))
          (setq (aref A j) temp)
          (incf pindex)))
    (incf j))
  (setq temp (aref A pindex))
  (setq (aref A pindex) pivot)
  (setq (aref A end) temp))

(quicksort 0 10)

一些错误,一行一行:

(print "Enter the elements of the array")
(setq k 10)                                 ; warning: no variable K
(setq A (make-array '(10)))                 ; warning: no variable A
(setq i 0)                                  ; warning: no variable I
(loop
  (if (>= i 10) (return))
  (setq x (read))
  (setf (aref A i) x)
  (incf i))                                 ; warning: k never used

(defun quicksort (start end)
  (if (< start end)
      (progn
        (setq pindex (lambda (start end)))  ; this lambda always returns nil
        (quicksort (start (- pindex 1)))    ; START is not a function
        (quicksort ((+ pindex 1) end)))))   ; (+ PINDEX 1) is not a function

(defun partition (start end)
  (setq pivot (aref A end))                 ; warning: no variable PIVOT
  (setq pindex start)                       ; warning: no variable PINDEX
  (setq j 0)                                ; warning: no variable J
  (loop
    (if (>= j end) return)                  ; warning: no variable RETURN
    (if (< (aref A j) pivot)
        (progn
          (setq temp (aref A pindex))       ; warning: no variable TEMP
          (setq pindex (aref A j))
          (setq (aref A j) temp)
          (incf pindex)))
    (incf j))
  (setq temp (aref A pindex))
  (setq (aref A pindex) pivot)
  (setq (aref A end) temp))

(quicksort 0 10)

摆脱“无变量”警告。 Setq不会引入变量。 大多数Common Lisp实现都做了一些有用的事情,这似乎有用, 但它是未定义的行为。您可以全局声明这些变量 特别是defvardefparameter,但你真正需要的是一个 用于读取用户输入的函数,您可以在其中使用let进行本地化 绑定。它还返回读取数组而不是设置全局状态。一世 还选择使用K作为参数以获得一些灵活性。 Finish-output 确保在输入第一个号码之前显示提示。

(defun read-integers (k)
  (print "Enter the elements of the array.")
  (finish-output)
  (let ((a (make-array (list k)))
        (i 0))
    (loop
      (if (>= i k)
          (return))
      (let ((x (read)))
        (setf (aref a i) x)
        (incf i)))
    a))

这仍然留有很大的改进空间,但至少它有效。

下一步:修复quicksort。因为除了运动之外它不会使用partition 一个空的lambda表单,我假设您想在那里调用partition。一世 还修复了调用表单和缺少绑定:

(defun quicksort (start end)
  (if (< start end)
      (let ((pindex (partition start end)))
        (quicksort start (- pindex 1))
        (quicksort (+ pindex 1) end))))

这是在全局数组上运行的,你在其中的任何地方都看不到 身体。这非常令人困惑,并使代码非常难以理解 难以维护。将数组作为参数给出来要好得多 将其称为(quicksort (read-integers 10) 0 10)

为了提高性能,我们需要在适当的位置进行操作,这是非常不寻常的 它应该在docstring中提到。我通常返回数组 sort的语义可以用于它。没有替代条款的IF是 写得更好。

(defun quicksort (array start end)
  "Destructively sorts ARRAY in place."
  (when (< start end)
    (let ((pindex (partition array start end)))
      (quicksort array start (- pindex 1))
      (quicksort array (+ pindex 1) end)))
  array)

这仍然包含一个一个错误,但我现在会看partition。 首先,解决通常的绑定问题:

(defun partition (array start end)
  "Chooses an arbitrary pivot element from array between START and END, then
destructively partitions the elements of ARRAY between START and END
in-place into those smaller than the pivot, then the pivot, then those
bigger than the pivot.  Finally returns the index of the pivot."
  ;; FIXME: doesn't work
  (let ((pivot (aref array end))
        (pindex start)
        (j 0))
    (loop
      (if (>= j end) (return))
      (if (< (aref array j) pivot)
          (let ((temp (aref array pindex)))
            (setf pindex (aref array j))
            (setf (aref array j) temp)
            (incf pindex)))
      (incf j))
    (let ((temp (aref array pindex)))
      (setf (aref array pindex) pivot)
      (setf (aref array end) temp))))

这是错的。请查看quicksort的工作原理。

提示:

  • 您需要两个索引变量
  • 你不应该在START和END之外引用数组的部分
  • 提示:使用rotatef
  • ,而不是通过显式临时位置手动交换
  • 提示:position-if可能有用。在Hyperspec中查找。
  • 提示:单独测试partition。如果有效,请修复quicksort

答案 1 :(得分:1)

如果您想在if的正文中使用多个语句,则不能围绕它们包裹( )。在Lisp中,parens有意义;他们不是为了分组。

您的选择

(if (< (aref A j) pivot)
    (progn
        (setq temp (aref A pindex))
        (setq pindex (aref A j))
        (setq (aref A j) temp)
        (incf pindex)))

(when (< (aref A j) pivot)
    (setq temp (aref A pindex))
    (setq pindex (aref A j))
    (setq (aref A j) temp)
    (incf pindex))