2013-09-29 196 views
4

我正在嘗試使用LISP進行快速排序,但我遇到了我的函數輸出問題。LISP中的快速排序

(defun qsort (L) 
    (cond 
    ((null L) nil) 
    (t(append 
     (qsort (list< (car L) (cdr L))) 
     (cons (car L) nil) 
     (qsort (list>= (car L) (cdr L))))))) 

(defun list< (a b) 
    (cond 
    ((or(null a)(null b) nil)) 
    ((< a (car b)) (list< a (cdr b))) 
    (t(cons (car b) (list< a (cdr b)))))) 

(defun list>= (a b) 
    (cond 
    ((or(null a)(null b) nil)) 
    ((>= a (car b)) (list> a (cdr b))) 
    (t(cons (car b) (list> a (cdr b)))))) 

我的問題是,當列表<列表> =完成列表總是以.T結束。例如:

> (list< '4 '(1 5 3 8 2)) 
Entering: LIST<, Argument list: (4 (1 5 3 8 2)) 
Entering: LIST<, Argument list: (4 (5 3 8 2)) 
    Entering: LIST<, Argument list: (4 (3 8 2)) 
    Entering: LIST<, Argument list: (4 (8 2)) 
    Entering: LIST<, Argument list: (4 (2)) 
    Entering: LIST<, Argument list: (4 NIL) 
    Exiting: LIST<, Value: T 
    Exiting: LIST<, Value: (2 . T) 
    Exiting: LIST<, Value: (2 . T) 
    Exiting: LIST<, Value: (3 2 . T) 
Exiting: LIST<, Value: (3 2 . T) 
Exiting: LIST<, Value: (1 3 2 . T) 
(1 3 2 . T) 

爲什麼(4 NIL)評估爲T?

+2

我一直指出[從_The Pitmanual_羊詭計(http://www.maclisp.info/pitmanual /funnies.html#sheep_trick)在Common Lisp中進行快速排序時出現。 –

+1

Downvoted for not formatting the source code。 –

回答

7

您的問題list<,還有list>=,位於((or (null a)(null b) nil)),它應該是((or(null a)(null b)) nil)。注意nil已被移出條件以作爲返回值。

此外,關於list>=的定義,您正在調用list>,但我確定您的意思是list>=

我還建議一些indentation解決口齒不清的可讀性,就像如下

(defun qsort (L) 
    (cond 
    ((null L) nil) 
    (t 
     (append 
     (qsort (list< (car L) (cdr L))) 
     (cons (car L) nil) 
     (qsort (list>= (car L) (cdr L))))))) 

(defun list< (a b) 
    (cond 
    ((or (null a) (null b)) nil) 
    ((< a (car b)) (list< a (cdr b))) 
    (t (cons (car b) (list< a (cdr b)))))) 

(defun list>= (a b) 
    (cond 
    ((or (null a) (null b)) nil) 
    ((>= a (car b)) (list>= a (cdr b))) 
    (t (cons (car b) (list>= a (cdr b)))))) 

一些測試如下:

(list< '4 '(1 5 3 8 2)) 
=> (1 3 2) 

(list>= '4 '(1 5 3 8 2)) 
=> (5 8) 

(qsort '(1 5 3 8 2)) 
=> (1 2 3 5 8) 
+0

當我在LISP中遇到問題時,我做的第一件事就是重寫我的括號,但我仍然錯過了它,是的,我在這裏寫下它時忘了=。謝謝。 – Shrp91

1

Lisp有不同類型的集合。我認爲使用快速排序來排序並不是一個好的選擇。在C++中實現STL時,list的排序方法是merge-sort。我試圖使用數組的集合來實現3路快速排序。

(defun quick-sort (arr start end) 
    "Quick sort body" 
    (if (< start end) 
    (let ((n-pair (partition arr start end))) 
    (quick-sort arr start (car n-pair)) 
    (quick-sort arr (cdr n-pair) end)) 
)) 

(defun partition (arr start end) 
"Partition according to pivot." 
(let ((pivot (aref arr start)) (cur start)) 
(loop while (<= start end) do 
    (cond 
    ((< pivot (aref arr start)) ; pivot < arr[start], swap with arr[end] 
    (swap arr start end) (decf end)) 
    ((> pivot (aref arr start)) ; pivot > arr[start], swap with arr[start] 
    (swap arr cur start) (incf cur) (incf start)) 
    (t       ; otherwise 
    (incf start)))) 
    (cons (decf cur) start))) 

(defun swap (arr i j) 
"Swap element of arr" 
(let ((tmp (aref arr i))) 
(setf (aref arr i) (aref arr j)) 
(setf (aref arr j) tmp))) 
+0

'Swap'被稱爲'rotatef'並且是標準的一部分。 – Svante

0

程序中有一些錯誤。校正程序是:

(defun qsort (L) 
    (cond 
    ((null L) nil) 
    (t (append 
     (qsort (list< (car L) (cdr L))) 
     (cons (car L) nil) 
     (qsort (list>= (car L) (cdr L))))))) 

(defun list< (a b) 
    (cond 
    ((or (null a) (null b)) nil) 
    ((< a (car b)) (list< a (cdr b))) 
    (t (cons (car b) (list< a (cdr b)))))) 

(defun list>= (a b) 
    (cond 
    ((or (null a)(null b)) nil) 
    ((>= a (car b)) (list>= a (cdr b))) 
    (t (cons (car b) (list>= a (cdr b)))))) 
1
(defun quick (list) 
    (when (< = (length list) 1) (return-from quick list)) 
    (let ((pivot (car list)) (rest (cdr list)) (less nil) (greater nil)) 
    (loop for i in rest do 
     (if (< i pivot) (push i less) (push i greater))) 
    (append (quick less) (list pivot) (quick greater)))) 
-1

這也應該工作:

(defun qsort (l) 
    (cond 
    ((null l) nil) 
    (t (append 
     (qsort (car(list<> (car l)(cdr l)))) 
     (cons (car l) nil) 
     (qsort (cadr(list<> (car l)(cdr l)))))))) 

(defun list<> (a b &optional rl rr) 
    (cond 
    ((null b) (list rl rr)) 
    ((<=(car b)a) (list<> a (cdr b) (cons (car b) rl) rr)) 
    (t (list<> a (cdr b)rl (cons (car b) rr))))) 

(setq l (loop for j from 1 to 20 append (list(random 100)))) 
(qsort l) 
;=> (86 99 9 31 66 58 57 43 48 21 51 0 32 69 39 47 59 76 69 23) 
;=> (0 9 21 23 31 32 39 43 47 48 51 57 58 59 66 69 69 76 86 99)