Scheme拆分操作不起作用

时间:2011-12-02 18:48:54

标签: list sorting split scheme

我是计划新手,在调试代码时遇到了一些麻烦。

; returns number of elements in a list
(define (length L)
  (cond ((null? L) 0)
        (else (+ (length (cdr L)) 1))))

; split the list in half:
; returns ((first half)(second half))
(define (split L)
  (cond 
    ((= (length L) 0) (list L L) )
    ((= (length L) 1) (list L '() ))
    (else 
      (list (sublist L 1 (/ (length L) 2) 1)
            (sublist L (+ (/ (length L) 2) 1) (length L) 1)))))

; extract elements start to end into a list
(define (sublist L start end counter)
  (cond ((null? L) L)
        ((< counter start) (sublist (cdr L) start end (+ counter 1)))
        ((> counter end) '())
        (else (cons (car L) (sublist (cdr L) start end (+ counter 1))))))

对我而言,这感觉就像将单个列表拆分为两个子列表一样。可能有一种更简单的方法,所以如果这看起来很麻烦,我会道歉。

无论如何,结果:

Expected: (split '(1 2 3 4 5)) = ('(1 2) '(3 4 5))
Actual:  (split '(1 2 3 4 5)) = ('(1 2) '(4 5))

很明显,lengthsplit正在失去中间值,但我一次又一次地检查它,似乎失去了中间值。似乎一个简单的解决办法就是摆脱(+ 1) (+ (/ (length L) 2) 1),但这对我来说似乎很直观,因为:

Assume L = '(1 2 3 4 5), (/ (length L) 2) = 2, and (+ (/ (length L) 2) 1) = 3
(sublist L 1 (2) 1) = '(1 2)
(sublist L (3) 5 1) = '(3 4 5)
** I put parens around the 2 and 3 to indicate that they were length calculations.

显然,我所做的假设是错误的,或者我忽略了一些微不足道的事情。

提前致谢!

3 个答案:

答案 0 :(得分:6)

你知道乌龟和野兔算法吗?乌龟走在名单上,野兔以双倍的速度奔跑。当野兔到达列表的末尾时,分裂发生在乌龟的位置。这是大部分代码;我会让你弄明白其余的事情:

(define (split xs)
  (let loop ((ts xs) (hs xs) (zs (list)))
    (if (or (null? hs) (null? (cdr hs)))
        (values (reverse zs) ts)
        (loop ...))))

这里ts是乌龟要检查的剩余物品清单,hs是野兔要检查的剩余物品清单,而zs是乌龟已经检查过的物品清单,顺序相反。 / p>

请注意,您永远不需要计算输入列表中的项目。

答案 1 :(得分:2)

我不打算为你调试你的代码。相反,这里有一个更简单的split定义:

(define (split l)
  (let ((n (length l)))
    (list (take (/ n 2) l)
          (drop (+ (/ n 2) (mod n 2)) l))))

为读者练习:实施takedrop。后者只是n的递归,同时在递归情况下取cdr l;前者需要稍微努力才能在基本情况下(停止条件)。

答案 2 :(得分:0)

这几乎是你的解决方案(球拍方案):

#lang racket

(define (length lst)
  (cond [(empty? lst) 0]
        [else (+ (length (rest lst)) 1)]))

(define (first-length lst)
  (quotient (length lst) 2))

(define (second-length lst)
  (- (length lst) (first-length lst)))

(define (sublist lst start end counter)
  (cond [(empty? lst) lst]
        [(< counter start) (sublist (rest lst) start end (+ counter 1))]
        [(> counter end) '()]
        [else (cons (first lst) (sublist (rest lst) start end (+ counter 1)))]))

(define (first-half-of-list lst)
  (sublist lst 1 (first-length lst) 1))

(define (second-half-of-list lst)
  (sublist lst (second-length lst) (length lst) 1))

(define (split lst)
  (cond
    [(= (length lst) 0) (list lst lst)]
    [(= (length lst) 1) (list lst '())]
    [else (list (first-half-of-list lst) 
                (second-half-of-list lst))]))

(split '(1 2 3 4 5))

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

感谢您进行良好的大脑锻炼。 关键时刻是“第二长度”功能。