如何修复我的快速排序实施?

时间:2013-04-01 21:19:51

标签: 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 (+ 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))))

我知道这种实现效率很低,但我想不出办法。无论如何,它并没有真正起作用。

When I input this:
(quicksort < '(9 3 -5 8 -7 2 9))
It gives me this:
(-7 -5 2 8 (8 9 9))
It should give me this:
(-7 -5 2 3 8 9 9)

我该如何解决这个问题?

修改

(define (join ls1 goo ls2)
  (if (null? ls1) (cons goo ls2)
      (if (null? ls2) (cons goo ls1)
          (cons (car ls1) (join (cdr ls1) goo ls2)))))

1 个答案:

答案 0 :(得分:1)

假设order过程与代码中使用下面几行的sort过程相同(等等,您是否正在使用排序过程来实现排序过程?!)和join是某种append,我可以得出结论,列表创建问题出现在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)

哎呀,数字3去了哪里?您的代码中存在错误,您必须找到它!提示:计算枢轴的代码非常错误。

修改

这是一个正确,无障碍的QuickSort实现。请注意,在这样的简单实现中,它足以选择第一个元素作为轴:

(define (quicksort cmp lst)
  (if (null? lst)
      '()
      (let ((x  (car lst))
            (xs (cdr lst)))
        (append (quicksort cmp (filter (lambda (e) (cmp e x)) xs))
                (list x)
                (quicksort cmp (filter (lambda (e) (not (cmp e x))) xs))))))

或使用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)))))))

另一种可能性,使用partition在一个步骤中获取两个分区(枢轴之前的元素和枢轴之后的元素) - 它更有效:

(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)