Scheme 如何修复快速排序实现?
下面是我实现快速排序的尝试:Scheme 如何修复快速排序实现?,scheme,quicksort,Scheme,Quicksort,下面是我实现快速排序的尝试: (define (sublist ls start stop middle) (cond ( (null? ls) ls) ( (< middle start) (sublist (cdr ls) start stop (+ middle 1))) ( (> middle stop) '() ) (else (cons (car ls) (sublist (cdr ls) start stop (+ mid
(define (sublist ls start stop middle)
(cond ( (null? ls) ls)
( (< middle start) (sublist (cdr ls) start stop (+ middle 1)))
( (> middle stop) '() )
(else
(cons (car ls) (sublist (cdr ls) start stop (+ middle 1))))))
(define (split5 ls)
(let ((len (length ls)))
(cond ((= len 0) (list ls ls) )
((= len 1) (list ls '() ))
(else
(list (sublist ls 1 (/ len 2) 1)
(sublist ls (+(/ len 2)1) len 1))))))
;this divides the sorted list into two sublists
(define (dividelist rel? ls)
(split5 (order rel? ls)))
(define (quicksort rel? ls)
(if (null? (cdr ls)) ls
(let ((pivot (list-ref (sort rel? ls) (round (/ (length (sort rel? ls)) 2))))
(left (car (dividelist rel? ls)))
(right (cdr (dividelist rel? ls))))
(join left pivot right))))
假设
order
过程与代码下面几行中使用的sort
过程相同(等等,您正在使用排序过程来实现排序过程?!),并且join
是一种追加
,我可以得出结论,列表创建的问题在于join
的实现。将其更改为此以修复它:
(define (join left pivot right)
(append* left (list pivot) right))
现在,该过程将返回一个列表,如下所示:
(quicksort < '(9 3 -5 8 -7 2 9))
=> '(-7 -5 2 8 8 9 9)
或者使用Racket的高阶程序,稍微更华丽、更短:
(define (quicksort cmp lst)
(if (empty? lst)
empty
(let ((x (first lst))
(xs (rest lst)))
(append (quicksort cmp (filter-not (curry cmp x) xs))
(cons x (quicksort cmp (filter (curry cmp x) xs)))))))
另一种可能性是,使用分区
在一个步骤中同时获得两个分区(轴之前的元素和轴之后的元素),效率更高:
(define (quicksort cmp lst)
(if (empty? lst)
empty
(let-values (((greater-than less-equal)
(partition (curry cmp (first lst)) (rest lst))))
(append (quicksort cmp less-equal)
(cons (first lst) (quicksort cmp greater-than))))))
无论如何,它的工作原理与预期相符:
(quicksort < '(9 3 -5 8 -7 2 9))
=> '(-7 -5 2 3 8 9 9)
(快速排序<'(93-58-729))
=> '(-7 -5 2 3 8 9 9)
不应该(右(cdr(dividelist rel?ls))
在快速排序结束时使用cadr
而不是cdr
?顺序在哪里?我希望这不是一个排序过程:P。另外,join
过程在哪里?…是的,order使用排序过程。“那很糟糕吗?”泰勒18当然。使用排序
实现快速排序
没有意义。从头开始实现排序过程的整个想法是手动执行排序,在其中使用另一个排序过程是毫无意义的。快速排序不依赖于是否存在另一个排序过程,而且选择枢轴的方式显然是错误的。只需选择第一个元素。并使用我的答案中所示的join
过程。
(define (quicksort cmp lst)
(if (empty? lst)
empty
(let ((x (first lst))
(xs (rest lst)))
(append (quicksort cmp (filter-not (curry cmp x) xs))
(cons x (quicksort cmp (filter (curry cmp x) xs)))))))
(define (quicksort cmp lst)
(if (empty? lst)
empty
(let-values (((greater-than less-equal)
(partition (curry cmp (first lst)) (rest lst))))
(append (quicksort cmp less-equal)
(cons (first lst) (quicksort cmp greater-than))))))
(quicksort < '(9 3 -5 8 -7 2 9))
=> '(-7 -5 2 3 8 9 9)