我比較懶惰棧和非懶堆棧實現從:http://en.wikibooks.org/wiki/F_Sharp_Programming/Advanced_Data_Structures#Lazy_Data_Structures爲什麼在F#中懶惰的純功能堆棧比非懶惰堆棧慢?
在這篇文章中,它說,附加功能是O(1)懶惰和O(n)的非懶。但是,在程序下面運行時,懶惰堆棧的速度比非懶惰速度慢兩倍。這可能是什麼原因?
type lazyStack<'a> =
| Node of // return an integer exit code
Lazy<'a * 'a lazyStack>
| EmptyStack
module LazyStack =
let (|Consx|Nil|) =
function
| Node(item) ->
let hd, tl = item.Force()
Consx(hd, tl)
| EmptyStack ->
Nil
let hd =
function
| Consx(hd, tl) -> hd
| Nil -> failwith "empty"
let tl =
function
| Consx(hd, tl) -> tl
| Nil -> failwith "empty"
let cons (hd, tl) = Node(lazy (hd, tl))
let empty = EmptyStack
let rec append x y =
match x with
| Consx(hd, tl) ->
Node(lazy (hd, append tl y))
| Nil ->
y
let rec iter f =
function
| Consx(hd, tl) ->
f (hd)
iter f tl
| Nil ->()
let doDummyWork i = i + 1
let x = cons (1, cons (2, cons (3, cons (4, EmptyStack))))
let y = cons (5, cons (6, cons (7, EmptyStack)))
let public dowork() =
let z = append x y
let z = append z y
()
hd z |> ignore
module Stack =
type stack<'a> =
| EmptyStack
| StackNode of 'a * 'a stack
let hd =
function
| EmptyStack -> failwith "Empty stack"
| StackNode(hd, tl) -> hd
let tl =
function
| EmptyStack -> failwith "Emtpy stack"
| StackNode(hd, tl) -> tl
let cons hd tl = StackNode(hd, tl)
let empty = EmptyStack
let rec update index value s =
match index, s with
| index, EmptyStack -> failwith "Index out of range"
| 0, StackNode(hd, tl) -> StackNode(value, tl)
| n, StackNode(hd, tl) -> StackNode(hd, update (index - 1) value tl)
let rec append x y =
match x with
| EmptyStack ->
y
| StackNode(hd, tl) ->
StackNode(hd, append tl y)
let rec map f =
function
| EmptyStack -> EmptyStack
| StackNode(hd, tl) -> StackNode(f hd, map f tl)
let rec rev s =
let rec loop acc =
function
| EmptyStack -> acc
| StackNode(hd, tl) -> loop (StackNode(hd, acc)) tl
loop EmptyStack s
let rec contains x =
function
| EmptyStack -> false
| StackNode(hd, tl) -> hd = x || contains x tl
let rec fold f seed =
function
| EmptyStack -> seed
| StackNode(hd, tl) -> fold f (f seed hd) tl
let rec iter f =
function
| StackNode(hd, tl) ->
f (hd)
iter f tl
| EmptyStack ->()
let doDummyWork i = i + 1
let x = StackNode(1, StackNode(2, StackNode(3, StackNode(4, EmptyStack))))
let y = StackNode(5, StackNode(6, StackNode(7, EmptyStack)))
let public dowork() =
let z = append x y
let z = append z y
hd z |> ignore
[<EntryPoint>]
let main argv =
let sw = System.Diagnostics.Stopwatch()
sw.Start()
let n = 1000000
for i = 0 to n do
Stack.dowork()
printfn "%A" sw.Elapsed
sw.Restart()
for i = 0 to n do
LazyStack.dowork()
printfn "%A" sw.Elapsed
0
如果您使用(多)更大的堆棧會發生什麼? – kvb 2014-11-06 18:13:58
是的更大的堆棧,懶惰的版本更好 – 2014-11-06 19:02:52