flatten'
は末尾再帰型なので、スタックスペースを取らないようにしてください。しかし、それは木の左側を歩いて、ヒープの束を吐き出します。あなたはあなたの例の木の上にそれを起動し、WHNFにそれを減らす場合は、このようなものを取得する必要があります:
:
/\
1 flatten' Tip :
/\
2 flatten' (Node 4) []
/ \
(Node 3) Tip
/ \
Tip Tip
アルゴリズムはO(N)
あるが、それはTip
のと同様にNode
Sを検討しています。
これは、順番にツリーを平坦化する最も効率的な方法です。 Data.Tree
モジュールはflatten
の機能hereを持っていますが、これは予約注文トラバーサルを好む以外は同じことをします。
更新:グラフ低減エンジンで
、main
でflatten
このようなグラフが生成されます。WHNFにこれを低減するために
@
/\
@ []
/\
/ \
/ \
flatten' Node 2
/ \
/ \
/ \
Node 1 Node 4
/ \ / \
Tip Tip/ \
/ \
Node 3 Tip
/ \
Tip Tip
を、グラフ低減エンジンは、アンロールされます背骨は[]
とNode 2
をスタックに押し込む。
@
/\
/ \
/ \
@ :
/\ /\
/ \ 2 \
/ \ \
flatten' Node 1 \
/ \ \
Tip Tip @
/\
@ []
/\
/ \
/ \
flatten' Node 4
/ \
/ \
/ \
Node 3 Tip
/ \
Tip Tip
そして、スタックから2つの引数をポップします。それは、このにグラフを書き換えますflatten'
関数を呼び出します。ルートノードはまだWHNFにはないので、グラフリダクションエンジンは背骨を展開し、2:...
とNode 1
をスタックにプッシュします。
@
/\
/ \
/ \
@ :
/\ /\
/ \ 1 \
/ \ \
flatten' Tip @
/\
/ \
/ :
@ /\
/\ 2 \
/Tip @
/ /\
flatten' @ []
/\
/ \
/ \
flatten' Node 4
/ \
/ \
/ \
Node 3 Tip
/ \
Tip Tip
そして、スタックから二つの引数をポップアップ表示されます:それは、これにグラフを書き換えますflatten'
機能を呼び出します。 WHNFにないルートノードはですが、であるため、グラフリダクションエンジンは背骨を展開し、1:...
とTip
をスタックにプッシュします。
:
/\
1 \
\
@
/\
/ \
/ :
@ /\
/\ 2 \
/Tip @
/ /\
flatten' @ []
/\
/ \
/ \
flatten' Node 4
/ \
/ \
/ \
Node 3 Tip
/ \
Tip Tip
そして、スタックから二つの引数をポップアップ表示されます:それは、これにグラフを書き換えますflatten'
機能を呼び出します。現在、WHNFには最大2つのスタックエントリを消費しています(Tree
のノードは、追加のスタック領域を必要とするサンクではありません)。
したがって、flatten'
は、テール再帰型です。追加のネストされたredexesを評価することなく、自身を置き換えます。 2番目のflatten'
は、スタックではなくヒープのサンクのままです。
出典
2012-05-15 04:40:27
pat
http://hackage.haskell.org/packages/archive/containers/latest/doc/html/src/Data-Map-Base.html#foldl –
luquiが指摘しているように、これは差分リスト手法です。 [this](http://stackoverflow.com/a/10584256/849891)と[this](http://stackoverflow.com/a/9550430/849891)も関連しています。 –