是否从ocaml中的循环/可变列表中删除循环?
我不知道如何从类型可变的列表中删除周期:是否从ocaml中的循环/可变列表中删除循环?,ocaml,mutable,cyclic,Ocaml,Mutable,Cyclic,我不知道如何从类型可变的列表中删除周期: type'a m|u list=Nil|Cons of'a*(('a m|list)ref) 例如,如果我有一个列表3,2,2,1,2,1,2,1,。。。。。我想要一个3,2,2,1。 我不知道初始循环的位置——我有一个递归,看起来像这样,但我不知道如何将其包装成递归函数;显然,这里它只会检查前几个术语 let remove list : unit = if is_cyclic list then match list with |Nil-&
type'a m|u list=Nil|Cons of'a*(('a m|list)ref)
例如,如果我有一个列表3,2,2,1,2,1,2,1,。。。。。我想要一个3,2,2,1。我不知道初始循环的位置——我有一个递归,看起来像这样,但我不知道如何将其包装成递归函数;显然,这里它只会检查前几个术语
let remove list : unit =
if is_cyclic list then match list with
|Nil->()
|Cons(_,v)-> match (!v) with
|Nil->()
|Cons(_,x)->match (!x) with
|Nil->()
|Cons(_,y)->match (!y) with
|Nil->()
|Cons(_,p) -> if is_cyclic (!p) then p:=Nil else ()
我有一个is_循环函数,它告诉我m_列表是否有循环。我想以破坏性的方式(更新引用)或非破坏性的方式(创建一个新列表)执行此操作
谢谢 根据您之前的问题,您可以尝试以下方法:
let rec recurse list already_visited =
match list with
Nil -> ()
| Cons(h, t) ->
if List.memq !t already_visited
then t := Nil
else recurse !t (t :: already_visited)
let remove_cycles list = recurse list []
这将遍历列表,直到它到达末尾或访问元素两次。当发生后一种情况时,它会将上次访问的引用设置为Nil
如果您有非常大的列表,您可能希望用另一个数据结构替换已访问的
。如果您没有足够的内存来存储以前访问的每个元素,您可以使用循环检测算法来查找循环中的元素,然后使用该算法,找到周期的结尾并覆盖它的下一个引用
为此,请修改is_cyclic
以返回一个'a mlist ref
,而不是bool
。假设它可能在循环中间返回一个元素,则运行原始列表并检查每个元素是否在循环中。这将为您提供循环中的第一个元素
从那里很容易找到循环的终点——只需在循环中循环,直到回到起点
大概是这样的:
let rec in_cycle x st cyc =
if cyc == x then true
else
match !cyc with Nil -> false
| Cons(_, t) when t == st -> false
| Cons(_, t) -> in_cycle x st t
let rec find_start l cyc =
if in_cycle l cyc cyc then l
else
match !l with Nil -> raise Not_found
| Cons(_, t) -> find_start t cyc
let rec find_end st cyc =
match !cyc with Nil -> raise Not_found
| Cons(_, t) ->
if t == st then cyc
else find_end st t
(* ... *)
let cyc = is_cyclic list in
let st = find_start list cyc in
let e = (find_end st cyc) in
match !e with Nil -> failwith "Error"
| Cons(v, _) -> e := Cons(v, ref Nil)