この関数を書いていたとき、末尾呼び出しの最適化が得られないことはわかっていました。私はまだこれを処理する良い方法を思いついておらず、他の誰かが提案を提供してくれることを望んでいました.
私は木を持っています:
type Heap<'a> =
| E
| T of int * 'a * Heap<'a> * Heap<'a>
そして、そこにあるノードの数を数えたい:
let count h =
let rec count' h acc =
match h with
| E -> 0 + acc
| T(_, value, leftChild, rightChild) ->
let acc = 1 + acc
(count' leftChild acc) + (count' rightChild acc)
count' h 0
これは、子ノードのカウントが追加されているため、最適化されていません。ツリーに 100 万個のノードがある場合、このようなものを作成する方法はありますか?
ありがとう、デレク
これは、CPS を使用した count の実装です。それでもスタックを吹き飛ばしました。
let count h =
let rec count' h acc cont =
match h with
| E -> cont (1 + acc)
| T(_,_,left,right) ->
let f = (fun lc -> count' right lc cont)
count' left acc f
count' h 0 (fun (x: int) -> x)
たぶん、スタックを吹き飛ばさずに数えられるように、ツリーを十分な数に分割する方法を思いつくことができるでしょうか?
誰かがツリーを生成するコードについて尋ねました。以下です。
member this.ParallelHeaps threads =
let rand = new Random()
let maxVal = 1000000
let rec heaper i h =
if i < 1 then
h
else
let heap = LeftistHeap.insert (rand.Next(100,2 * maxVal)) h
heaper (i - 1) heap
let heaps = Array.create threads E
printfn "Creating heap of %d elements, with %d threads" maxVal threads
let startTime = DateTime.Now
seq { for i in 0 .. (threads - 1) ->
async { Array.set heaps i (heaper (maxVal / threads) E) }}
|> Async.Parallel
|> Async.RunSynchronously
|> ignore
printfn "Creating %d sub-heaps took %f milliseconds" threads (DateTime.Now - startTime).TotalMilliseconds
let startTime = DateTime.Now
Array.length heaps |> should_ equal threads <| "The size of the heaps array should match the number of threads to process the heaps"
let rec reMerge i h =
match i with
| -1 -> h
| _ ->
printfn "heap[%d].count = %d" i (LeftistHeap.count heaps.[i])
LeftistHeap.merge heaps.[i] (reMerge (i-1) h)
let heap = reMerge (threads-1) E
printfn "Merging %d heaps took %f milliseconds" threads (DateTime.Now - startTime).TotalMilliseconds
printfn "heap min: %d" (LeftistHeap.findMin heap)
LeftistHeap.count heap |> should_ equal maxVal <| "The count of the reMerged heap should equal maxVal"