您可以使用 John Hughes 的恒定时间附加列表,现在似乎称为 DList。表示是一个从列表到列表的函数:空列表是恒等函数; append 是组合,而单例是 cons(部分应用)。在这种表示中,每个枚举都会花费您n 分配,因此可能不太好。
另一种方法是制作与数据结构相同的代数:
type 'a seq = Empty | Single of 'a | Append of 'a seq * 'a seq
枚举是一种树遍历,它要么会消耗一些堆栈空间,要么需要某种拉链表示。这是一个转换为列表但使用堆栈空间的树遍历:
let to_list t =
let rec walk t xs = match t with
| Empty -> xs
| Single x -> x :: xs
| Append (t1, t2) -> walk t1 (walk t2 xs) in
walk t []
这里是一样的,但是使用了常量栈空间:
let to_list' t =
let rec walk lefts t xs = match t with
| Empty -> finish lefts xs
| Single x -> finish lefts (x :: xs)
| Append (t1, t2) -> walk (t1 :: lefts) t2 xs
and finish lefts xs = match lefts with
| [] -> xs
| t::ts -> walk ts t xs in
walk [] t []
您可以编写一个折叠函数来访问相同的元素,但实际上并不具体化列表;只需将 cons 和 nil 替换为更通用的内容即可:
val fold : ('a * 'b -> 'b) -> 'b -> 'a seq -> 'b
let fold f z t =
let rec walk lefts t xs = match t with
| Empty -> finish lefts xs
| Single x -> finish lefts (f (x, xs))
| Append (t1, t2) -> walk (t1 :: lefts) t2 xs
and finish lefts xs = match lefts with
| [] -> xs
| t::ts -> walk ts t xs in
walk [] t z
这是您的线性时间、常量堆栈枚举。玩得开心!