flatten'
ist Tail rekursiv, so sollte es keinen Stapelplatz nehmen. Es wird jedoch auf der linken Seite des Baumes gehen und einen Haufen Dinger in den Haufen spucken.Wenn Sie es auf Ihrem Beispiel Baum aufrufen, und reduzieren sie auf WHNF, sollten Sie etwas, das wie folgt aussieht:
:
/\
1 flatten' Tip :
/\
2 flatten' (Node 4) []
/ \
(Node 3) Tip
/ \
Tip Tip
Der Algorithmus ist O(N)
, aber es hat die Tip
s sowie die Node
s zu untersuchen .
Dies scheint der effizienteste Weg zu sein, um Ihren Baum in Ordnung zu bringen. Das Modul Data.Tree
hat eine flatten
Funktion here, die fast dasselbe tut, außer dass es eine Vorbestellung bevorzugt.
Update:
In einem Diagramm Reduzierungs-Engine, die flatten
in main
eine grafische Darstellung wie folgt erzeugen:
@
/\
@ []
/\
/ \
/ \
flatten' Node 2
/ \
/ \
/ \
Node 1 Node 4
/ \ / \
Tip Tip/ \
/ \
Node 3 Tip
/ \
Tip Tip
Um dies zu WHNF zu reduzieren, wird die Graphreduktions Motor entrollen die Wirbelsäule, schieben Sie die []
und die Node 2
auf den Stapel. Es wird dann rufen Sie die flatten'
-Funktion, die die Grafik wird dieses umschreiben:
@
/\
/ \
/ \
@ :
/\ /\
/ \ 2 \
/ \ \
flatten' Node 1 \
/ \ \
Tip Tip @
/\
@ []
/\
/ \
/ \
flatten' Node 4
/ \
/ \
/ \
Node 3 Tip
/ \
Tip Tip
Und wird die beiden Argumente vom Stapel Pop. Der Wurzelknoten befindet sich immer noch nicht in WHNF, daher wird die Graph-Verkleinerungs-Engine den Rücken abrollen und die 2:...
und die Node 1
auf den Stapel schieben. Es wird dann rufen Sie die flatten'
-Funktion, die die Grafik wird dieses umschreiben:
@
/\
/ \
/ \
@ :
/\ /\
/ \ 1 \
/ \ \
flatten' Tip @
/\
/ \
/ :
@ /\
/\ 2 \
/Tip @
/ /\
flatten' @ []
/\
/ \
/ \
flatten' Node 4
/ \
/ \
/ \
Node 3 Tip
/ \
Tip Tip
Und wird die beiden Argumente vom Stapel Pop. Der Wurzelknoten ist immer noch nicht in WHNF, so wird die Grafik-Reduktions-Engine die Wirbelsäule ausrollen, die 1:...
und die Tip
auf den Stapel schieben. Es wird dann rufen Sie die flatten'
-Funktion, die die Grafik wird dieses umschreiben:
:
/\
1 \
\
@
/\
/ \
/ :
@ /\
/\ 2 \
/Tip @
/ /\
flatten' @ []
/\
/ \
/ \
flatten' Node 4
/ \
/ \
/ \
Node 3 Tip
/ \
Tip Tip
Und wird die beiden Argumente vom Stapel Pop. Wir befinden uns jetzt in WHNF, nachdem wir maximal zwei Stack-Einträge verbraucht haben (unter der Annahme, dass die Tree
-Knoten keine Thunks waren, die zusätzlichen Stack-Speicherplatz zum Auswerten benötigten).
Also, flatten'
ist Tail-rekursiv. Es ersetzt sich selbst, ohne zusätzliche verschachtelte Redexes auswerten zu müssen. Die zweite flatten'
bleibt ein Thunk im Heap, nicht der Stapel.
http://hackage.haskell.org/packages/archive/containers/latest/doc/html/src/Data-Map-Base.html#foldl –
Wie Luqui hervorhebt, ist dies eine Differenzlistentechnik. [this] (http://stackoverflow.com/a/10584256/849891) und [dies] (http://stackoverflow.com/a/9550430/849891) sind ebenfalls verwandt. –