如何在scheme中对无序的数字列表进行排序

如何在scheme中对无序的数字列表进行排序,scheme,Scheme,使用Scheme中的值对列表进行排序的正确方法是什么?例如,我有未排序的值: x1, x5, x32 .... xn 或 首先,我想通过增加数字来显示它们,并按以下顺序显示它们: x1, xn, x2, xn-1 或 任何帮助都是有价值的。这是您发布的同一个问题,但有一个小的转折。正如我在我的评论中告诉你的,你只需要在重新排列列表之前对列表进行排序。这里有一个球拍解决方案: (define (interleave l1 l2) (cond ((empty? l1) l2)

使用Scheme中的值对列表进行排序的正确方法是什么?例如,我有未排序的值:

x1, x5, x32 .... xn

首先,我想通过增加数字来显示它们,并按以下顺序显示它们:

x1, xn, x2, xn-1


任何帮助都是有价值的。

这是您发布的同一个问题,但有一个小的转折。正如我在我的评论中告诉你的,你只需要在重新排列列表之前对列表进行排序。这里有一个球拍解决方案:

(define (interleave l1 l2)
  (cond ((empty? l1) l2)
        ((empty? l2) l1)
        (else (cons (first l1)
                    (interleave l2 (rest l1))))))

(define (zippy lst)
  (let-values (((head tail) (split-at
                             (sort lst <) ; this is the new part
                             (quotient (length lst) 2))))
    (interleave head (reverse tail))))

这是你贴的同一个问题,但有一个小转折。正如我在我的评论中告诉你的,你只需要在重新排列列表之前对列表进行排序。这里有一个球拍解决方案:

(define (interleave l1 l2)
  (cond ((empty? l1) l2)
        ((empty? l2) l1)
        (else (cons (first l1)
                    (interleave l2 (rest l1))))))

(define (zippy lst)
  (let-values (((head tail) (split-at
                             (sort lst <) ; this is the new part
                             (quotient (length lst) 2))))
    (interleave head (reverse tail))))

这个R6RS解决方案实现了Chris Jester Young的建议,实际上就是如何以糟糕的方式实现它。顺便说一句,Chris和Óscar的解决方案在没有排序的情况下优于这种快速程序

    #!r6rs
    (import (rnrs base)
            (rnrs sorting)) ; list-sort

    (define (zippy lis)
      (let loop ((count-down (- (length lis) 1))
                 (count-up 0))
        (cond ((> count-up count-down) '())
              ((= count-up count-down) (cons (list-ref lis count-down) '()))
              (else (cons (list-ref lis count-down)
                          (cons (list-ref lis count-up)
                                (loop (- count-down 1)
                                      (+ count-up 1))))))))
    (define (sort-rearrange lis)
      (zippy (list-sort < lis)))

这个R6RS解决方案实现了Chris Jester Young的建议,实际上就是如何以糟糕的方式实现它。顺便说一句,Chris和Óscar的解决方案在没有排序的情况下优于这种快速程序

    #!r6rs
    (import (rnrs base)
            (rnrs sorting)) ; list-sort

    (define (zippy lis)
      (let loop ((count-down (- (length lis) 1))
                 (count-up 0))
        (cond ((> count-up count-down) '())
              ((= count-up count-down) (cons (list-ref lis count-down) '()))
              (else (cons (list-ref lis count-down)
                          (cons (list-ref lis count-up)
                                (loop (- count-down 1)
                                      (+ count-up 1))))))))
    (define (sort-rearrange lis)
      (zippy (list-sort < lis)))

下面是一种简单的尾部递归方法,它使用“慢/快”技术在遍历列表的一半时停止递归:

(define (interleave l)
  (let ((l (list-sort < l)))
    (let merging ((slow l) (fast l) (revl (reverse l)) (rslt '()))
      (cond ((null? fast)
             (reverse rslt))

            ((null? (cdr fast)) 
             (reverse (cons (car slow) rslt)))

            (else
             (merging (cdr slow) (cddr fast) (cdr revl)
                      (cons (car revl) (cons (car slow) rslt))))))))

下面是一种简单的尾部递归方法,它使用“慢/快”技术在遍历列表的一半时停止递归:

(define (interleave l)
  (let ((l (list-sort < l)))
    (let merging ((slow l) (fast l) (revl (reverse l)) (rslt '()))
      (cond ((null? fast)
             (reverse rslt))

            ((null? (cdr fast)) 
             (reverse (cons (car slow) rslt)))

            (else
             (merging (cdr slow) (cddr fast) (cdr revl)
                      (cons (car revl) (cons (car slow) rslt))))))))

所以,你不介意慢下来,只是想要一种基于选择的方法,是吗?我们走吧

首先,我们定义一个select1函数,该函数获取最小或最大元素,然后是所有其他元素。对于链表,这可能是最简单的方法,比尝试实现say quickselect更容易

(define (select1 lst cmp?)
  (let loop ((seen '())
             (rest lst)
             (ext #f)
             (extseen '()))
    (cond ((null? rest)
           (cons (car ext) (append-reverse (cdr extseen) (cdr ext))))
          ((or (not ext) (cmp? (car rest) (car ext)))
           (let ((newseen (cons (car rest) seen)))
             (loop newseen (cdr rest) rest newseen)))
          (else
           (loop (cons (car rest) seen) (cdr rest) ext extseen)))))
现在实际进行交织:

(define (zippy lst)
  (let recur ((lst lst)
              (left? #t))
    (if (null? lst)
        '()
        (let ((selected (select1 lst (if left? < >))))
          (cons (car selected) (recur (cdr selected) (not left?)))))))

这种方法是开着的,而这里其他人推荐的排序和交织方法是在logn上的。

所以,你不介意慢一点,只是想要一种基于选择的方法,是吗?我们走吧

首先,我们定义一个select1函数,该函数获取最小或最大元素,然后是所有其他元素。对于链表,这可能是最简单的方法,比尝试实现say quickselect更容易

(define (select1 lst cmp?)
  (let loop ((seen '())
             (rest lst)
             (ext #f)
             (extseen '()))
    (cond ((null? rest)
           (cons (car ext) (append-reverse (cdr extseen) (cdr ext))))
          ((or (not ext) (cmp? (car rest) (car ext)))
           (let ((newseen (cons (car rest) seen)))
             (loop newseen (cdr rest) rest newseen)))
          (else
           (loop (cons (car rest) seen) (cdr rest) ext extseen)))))
现在实际进行交织:

(define (zippy lst)
  (let recur ((lst lst)
              (left? #t))
    (if (null? lst)
        '()
        (let ((selected (select1 lst (if left? < >))))
          (cons (car selected) (recur (cdr selected) (not left?)))))))

这个方法是On²,而这里其他人推荐的排序和交织方法是在log n上。

顺便问一下,还有其他方法可以解决这个任务吗?这是可行的,但我正在寻找其他方法。例如,有什么算法可以使用吗?@Peter你可以对每个位置使用选择,例如,但它会非常慢!你能告诉我如何通过选择每个职位来解决这个问题吗。速度不是问题。@PeterPenzov你还想用什么方法?您询问是否有任何算法可以使用-当然,上面显示的排序算法:P。如果不先对列表进行排序,就试图以您想要的方式重新排列元素,那么结果将至少与先对元素进行排序一样慢(如果不是更糟的话),因为所需的排序隐含地需要一个已排序的列表。那就先把它分类吧@PeterPenzov嗯,关于我刚才描述的方法,我发表了一篇单独的帖子,但是相信我,它不如排序优先的方法。顺便问一下,还有其他方法可以解决这个问题吗?这是可行的,但我正在寻找其他方法。例如,有什么算法可以使用吗?@Peter你可以对每个位置使用选择,例如,但它会非常慢!你能告诉我如何通过选择每个职位来解决这个问题吗。速度不是问题。@PeterPenzov你还想用什么方法?您询问是否有任何算法可以使用-当然,上面显示的排序算法:P。如果不先对列表进行排序,就试图以您想要的方式重新排列元素,那么结果将至少与先对元素进行排序一样慢(如果不是更糟的话),因为所需的排序隐含地需要一个已排序的列表。那就先把它分类吧@PeterPenzov嗯,关于我刚才描述的方法,我发表了一篇单独的帖子,但是相信我,它不如排序优先的方法。