Да, вывод правильный.
> (my-append '(a b '(1 2 3)) (list '(4 5 6) 7 8 9))
(list 'a 'b (list 'quote (list 1 2 3)) (list 4 5 6) 7 8 9)
Он напечатан в стиле, так что при вставке обратно в приглашении результат будет таким же:
> (list 'a 'b (list 'quote (list 1 2 3)) (list 4 5 6) 7 8 9)
(list 'a 'b (list 'quote (list 1 2 3)) (list 4 5 6) 7 8 9) ; compare below vvvvv
Как мы можем быть уверены, что все в порядке?Делая то же самое с двумя частями:
> '(a b '(1 2 3))
(list 'a 'b (list 'quote (list 1 2 3)))
; --------------------------------
> (list '(4 5 6) 7 8 9)
(list (list 4 5 6) 7 8 9) ; aligned vertically ^^^
; ------------------
Приложение просто объединяет две части в один список, превращая
(list a b c ... n) (list o p q ... z)
в
(list a b c ... n o p q ... z)
или, символически ("в псевдокод "),
[a b c ... n] [o p q ... z] ; is turned into:
[a b c ... n o p q ... z]
О вашем алгоритме.Он добавляет два списка, повторяя шаги
[a b c ... n] [o p q ... z]
[a b c ... n] o [p q ... z]
[a b c ... n o] [q ... z]
, пока второй список не будет исчерпан.Повторное добавление элемента в конец списка хорошо подходит для языков с таким примитивом, как Clojure conj
, который дешев в использовании.Но в Схеме это алгоритмически невыгодно, поскольку повторный обход первого списка для добавления элемента к нему приводит к поведению квадратичного относительно сложности времени (время выполнения вырастет в четыре раза в два разаувеличение размера входных данных).
Еще один способ сделать это -
[a b ... m n] [o p q ... z]
[a b ... m] n [o p q ... z]
[a b ... m] [n o p q ... z]
, пока не будет использован первый список:
(define my-append-helper
(lambda (L1 L2)
(cond ( (equal? '() L1)
L2)
(else (my-append-helper (but-last L1) (cons (last L1) L2))))))
; ^^^^ !
cons
дешево в Схеме, так что это хорошо.Но многократное удаление элемента из конца списка (с еще не реализованным but-last
) является алгоритмически невыгодным, поскольку повторный обход первого списка для удаления его последнего элемента приводит к квадратичному поведению в отношениисложность времени (время выполнения вырастет в четыре раза при увеличении размера входных данных в два раза).
Мы на правильном пути с cons
, хотя, когда мы замечаем, что добавлениеможет прогрессировать по шагам
[a b ... m n] [o p q ... z]
( [a] [b ... m n] ) [o p q ... z]
[a] ( [b ... m n] [o p q ... z] )
................................
[a] [b ... m n o p q ... z]
[a b ... m n o p q ... z]
, если мы выделим элемент first из списка first , добавим то, что осталось, а затем все, что осталось для насчтобы сделать это cons
этот первый элемент на результат!