Sort a list in scheme

前端 未结 2 468
深忆病人
深忆病人 2021-01-22 22:49

I want to create function which sorts list. For example I have this list:

x1, x2, x3 .... xn

or

1, 2, 3, 4, 5, 6

相关标签:
2条回答
  • 2021-01-22 23:00

    Usually when we talk about sorting, we refer to ordering the items by some characteristic of the item contents, not the item position in the list. I would call your situation permuting, but perhaps some people might dispute that usage, too. :-)

    Here's how you might approach the problem:

    1. Split the list in the middle (you can do this using tortoise-and-hare if you only want to traverse the list once); call those lists head and tail, if you want.
    2. Reverse the tail list, and interleave it with the head list.

    Another approach:

    1. Reverse the original list pairs (let's call it rev).
    2. Interleave the original list with rev, keeping track of the element traversed each time. When they meet in the middle, stop.

    Here's a demonstration of the second approach (requires SRFI 1 to be loaded):

    (define (zippy lst)
      (if (null? lst)
          '()
          (let recur ((lst lst)
                      (rev (pair-fold cons '() lst)))
            (cond ((eq? lst (car rev)) (list (car lst)))
                  ((eq? (cdr lst) (car rev)) (list (car lst) (caar rev)))
                  (else (cons* (car lst) (caar rev)
                               (recur (cdr lst) (cdr rev))))))))
    
    0 讨论(0)
  • 2021-01-22 23:00

    This is not really a sorting operation, more like a shuffling; here's another way to solve it. First, let's define the interleave procedure that alternates elements from two lists, returning a single list:

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

    Now we take the original list and split-at the middle (this is a Racket-specific procedure); finally we interleave the two resulting lists, reversing the tail:

    (define (zippy lst)
      (let-values (((head tail) (split-at lst (quotient (length lst) 2))))
        (interleave head (reverse tail))))
    

    The above implementation IMHO is a bit more intuitive, and if you're working with Racket it doesn't require external libraries. It works as expected:

    (zippy '(1 2 3 4 5 6))
    => '(1 6 2 5 3 4)
    
    0 讨论(0)
提交回复
热议问题