0

I am reading Section 2.2 in SICP where the book introduced the procedure for appending two lists. I am trying to implement the append using iteration.

This is my code:

(define (append list1 list2)
  (define (append-iter item1 reversed-item1 result)
    (if (null? item1)
      (if (null? reversed-item1)
        result
        (append-iter item1 
                     (cdr reversed-item1) 
                     (cons (car reverse) result)))
      (append-iter (cdr item1) 
                   (cons (car item1) reversed-item1) 
                   result)))
  (append-iter list1 '() list2))

Though it works, but noting the number of the iterations is double the length of list1. Is there a solution whose number of the iterations equals to the length of list1. (without using any fold function)?

Xiaojun Chen
  • 1,222
  • 2
  • 12
  • 21

1 Answers1

1

Basically how your procedure works is like this:

(define (append l1 l2)
  (define (reverse-append rev app)
    (if (null? rev)
        app
        (reverse-append (cdr rev) 
                        (cons (car rev) app))))
  (reverse-append (reverse l1) l2))   

It's O(N) but it wastes some memory since (reverse l1) space is just used for iteration. If you really need to fix that you need to use mutation:

(define (append-iter . rest)
  (let ((result (list 1)))
    (let loop ((p result) (lst '()) (rest rest))
      (cond
        ((not (null? lst))
         (set-cdr! p (list (car lst)))
         (loop (cdr p) (cdr lst) rest))
        ((null? rest) (cdr result))
        ((null? (cdr rest))
         (set-cdr! p (car rest))
         (cdr result))
        (else (loop p (car rest) (cdr rest)))))))
Sylwester
  • 47,942
  • 4
  • 47
  • 79