這裏是我的解決方案:
(define (flatten-iter a-list)
(define (flat-do acc lst-interm lst)
(cond
((null? lst)
(reverse acc))
((and (list? lst-interm) (not (null? lst-interm)))
(flat-do acc (car lst-interm) (append (cdr lst-interm) lst)))
((not (list? lst-interm))
(flat-do (cons lst-interm acc) empty lst))
((list? (car lst))
(flat-do acc (car lst) (cdr lst)))
(else
(flat-do (cons (car lst) acc) empty (cdr lst)))))
(flat-do empty empty a-list))
(flatten-iter (list 1 (list 2 (list 3 4 (list 5 empty 6))) 7 8))
=> (1 2 3 4 5 6 7 8)
尾recrusive功能要求,他們不會再回來,這樣的話你不能用於存儲程序的狀態使用堆棧。而是使用函數參數在函數調用之間傳遞狀態。因此,我們需要確定如何維持這個狀態。由於我們的功能的結果是list?
,所以增加一個empty
列表是有意義的;我們正在爲此使用acc
。你可以看到它在else
分支上面如何工作。但是我們應該能夠處理嵌套列表。而且,當我們進一步深入時,我們應該保留嵌套列表的其餘元素以供進一步處理。示例列表:(list 1 (list 2 3) 4 5)
直到(list 2 3)
我們已經將1
添加到累加器。由於我們不能使用堆棧,我們需要其他地方來存儲列表的其餘元素。而這個地方是lst
的參數,其中包含要扁平化的原始列表的元素。我們只需append
lst
其餘元素(cdr (list 2 3))
這是(list 3)
,並繼續清單的頭,我們無意中扁平化,即我。即(汽車(名單2 3)),這只是2
。現在,(and (list? lst-interm) (not (null? lst-interm)))
成功,因爲flat-do
被稱爲是這樣的:
(flat-do (list 1) (list 2 3) (list 4 5))
和條件觸發此代碼:
(flat-do (list 1) (car (list 2 3)) (append (cdr (list 2 3)) (list 4 5)))
再次flat-do
被稱爲是這樣的:(平-DO(表1)2(名單3 4 5))
條件(not (list? 2))
現在成功並且代碼(flat-do (cons 2 1) empty (list 3 4 5))
進行評價。
其餘處理與else
分支做,直到lst
是null?
和reverse
上acc
執行。函數然後返回反向累加器。
希望我有能力感謝您的快速回復,Yasir。讀完之後,我明白它在做什麼(這很重要),但如果你能夠提醒我關注你的思維過程,我會非常感激。對不起,如果我要求太多!並且非常感謝迄今爲止的幫助。 – Mamsaac 2011-03-21 09:30:51
Mamsaac:我現在要吃我的披薩了。如果你不介意,讓我稍後更詳細地解釋它:-) – 2011-03-21 09:34:34
Buen provencho :)(享受你的用餐) – Mamsaac 2011-03-21 09:38:24