3

我挑战自己在 Common Lisp 的算法课上完成所有作业。我进入学习 lisp 的第一天,但​​遇到了障碍。

任务是创建一个合并排序,当您达到任意子集长度时转换为插入(Timsort)。插入部分完美运行,但合并的拆分部分仅在程序必须拆分两次时才有效。我知道这与列表在 lisp 中的工作方式有关,我太新了,无法查明问题。

我认为它要么遇到无限循环......我不确定,因为当我使用调试语句运行它时,当集合中有太多元素时它们永远不会被打印出来。

我不是在这里乞求具体的答案或有人写我的代码。也许一个解释或一个正确方向的观点会有很大帮助!

我的代码:

;; Insertion sort method call (returns sorted list)
(defun insert-sort (lst) ... )

;; Merge sort method call
(defun merge-sort (lst)
  (print 'Merge)
  (print lst)
  (if (< (length lst) 7) ; Check to see if list is small enough to insert sort
      (insert-sort lst) ; Do so
      (progn ; else
        (setf b (merge-split lst)) ; Split the list, store into b
        (setf (car b) (merge-sort (car b))) ; Merge sort on first half
        ;; --- I think it's happening here ---
        (setf (cdr b) (merge-sort (cdr b))) ; Merge sort on second half
        (merge 'list (car b) (cdr b) #'<)))) ; Merge the two lists together (using API)

;; Split a list into two parts
(defun merge-split (lst)
   (progn
     (setf b lst) ; Set b to first index
     (setf a (cdr lst)) ; Set a to the rest of the list
     (loop while a do ; Loop while a != null
           (setf a (cdr a)) ; Make a equal next list node
           (if a ; If it still exists
               (progn
                 (setf a (cdr a)) ; Inc a again
                 (setf b (cdr b))))) ; Also inc b (b should always be half of a)
     (setf a (cdr b)) ; Set a to the list after b
     (setf (cdr b) NIL) ; Delete link after b
     (cons lst a))) ; Return in a cons

注意:这是我写的代码,不是从互联网上下载的......你可能会知道哈哈

4

1 回答 1

4

您被动态范围的变量所困扰。第一次调用 SETF 设置 a、b 时,您隐式地创建了全局的、动态范围的变量。改用 LET 来声明它们。LET 允许您包含要执行的表达式列表,就像 PROGN 一样,所以我的提示是您可以通过将 2 个 PROGN 更改为 LET 来解决此问题。让我知道您是否需要更多才能摆脱困境。

于 2012-01-26T01:05:31.113 回答