如何实现具有链接列表样式和就地修改的堆栈?

时间:2013-02-20 23:18:04

标签: functional-programming ocaml

Java中,很容易实现linkedlist样式的stack

我们只创建一个内部类Item,它有两个属性:valuenext

然后我们总是第一项。

然后在push时,我们创建一个新的Item并让其下一个指向当前的first item,然后让当前的first item成为新的item }。

可以与pop类似。


但是我怎么能在OCaml中做到这一点?特别是当我们想要in place modificationmutable)?

我说mutable因为正常pop只会弹出值,而不是新堆栈。

2 个答案:

答案 0 :(得分:4)

OCaml是一种多范式语言。使用可变数据并不困难。但是如果没有它(恕我直言),这是值得努力的。这个好处非常好,成本也非常低。

尽管如此,这里是一个可变堆栈类型的快速草图。

type 'a stack = { mutable stack: 'a list }

let new_stack () = { stack = [] }

let is_empty stack = stack.stack = []

let push x stack = stack.stack <- x :: stack.stack

let pop stack =
    match stack.stack with
    | [] -> raise Not_found
    | x :: xs -> stack.stack <- xs; x

(您也可以从定义type 'a stack = 'a list ref开始,但此版本显示了如何拥有自己的可变记录字段。)

答案 1 :(得分:2)

为了补充杰弗里的优秀答案,我想在此注意到 在这种情况下,很容易实现两者持久性接口和 Stack数据结构的可变接口,作为可变的 接口可以构建在持久接口之上。

module Impl = struct
  type 'a t = 'a list
  let empty = []
  let is_empty = function [] -> true | _ -> false
  let push x stack = x::stack

  let pop = function
    | [] -> raise Not_found
    | x::xs -> (x,xs)
end

module PersistentStack : sig
  type +'a t
  val empty : 'a t
  val is_empty : 'a t -> bool
  val push : 'a -> 'a t -> 'a t
  val pop : 'a t -> 'a * 'a t
end = struct
  include Impl
end

module MutableStack : sig
  type 'a t
  val new_stack : unit -> 'a t
  val is_empty : 'a t -> bool
  val push : 'a -> 'a t -> unit
  val pop : 'a t -> 'a
end = struct
  type 'a t = 'a Impl.t ref
  let new_stack () = ref Impl.empty
  let is_empty stack = Impl.is_empty !stack
  let push x stack = (stack := Impl.push x !stack)
  let pop stack =
    let (x, xs) = Impl.pop !stack in
    stack := xs;
    x
end