我是LISP的新手。我试图在LISP中编写冒泡排序功能。
这是我迄今为止所做的。
(defun mysort (x)
(if (null x) x
(if (< (car x) (cadr x))
(cons (car x) (mysort (cdr l)))
(cons (cadr x) (mysort (cons (car x) (cddr x)))))))
我收到错误
NIL is not a real number
当我修改代码时(在引用几个代码之后) -
(defun mysort (x)
(if (null (cdr x)) x
(if (< (car x) (cadr x))
(cons (car x) (mysort (cdr l)))
(cons (cadr x) (mysort (cons (car x) (cddr x)))))))
现在工作正常。
为什么要更换 (if(null x)x ...) 同 (if(null(cdr x))x ...) 有所作为?
另外,我从另一个函数调用mysort来运行它(长度x)次数。是否可以在单个递归循环中实现完全排序,只使用基本函数?
答案 0 :(得分:4)
如果你想看第一个元素是否小于第二个元素,那么列表需要至少有两个元素。
如果只有一个元素,CADR
会返回NIL
。这不是一个数字。
CL-USER 18 > (cadr '(1))
NIL
您的Lisp系统不仅应该告诉您错误,还应该告诉您发生错误的函数。这里:函数<
。
使用(null (cdr list))
是测试是否存在第二个元素的好方法。典型的错误是调用LENGTH
,效率很低。
答案 1 :(得分:1)
要进行比较,您至少需要两个元素,因此检查x
是否NIL
是不够的。
检查(cdr x)
是否为NIL
是检查列表长度是否至少为2的好方法,因为NIL
是特殊的,即使它不是一个缺点单元格它保证(cdr NIL)
为NIL
。
您收到的错误是因为NIL
不是数字,因此您无法与<
数字进行比较,而(< (car x) (cadr x))
执行x
时会发生这种情况是一个包含单个元素的列表。
关于在单个递归调用中进行排序,您可以使用此排序定义:
这导致
(defun mysort (x)
(if x
(let ((minimum (reduce #'min x)))
(cons minimum
(mysort (remove minimum x :count 1))))))
顺便说一下,这是一种非常低效的排序方式。