List 创建双链接列表的实例

List 创建双链接列表的实例,list,ocaml,circular-reference,List,Ocaml,Circular Reference,我得到了以下双链接列表的实现: type 'a elem = {v : 'a; mutable next : 'a lista; mutable prev : 'a lista} and 'a lista = 'a elem option;; 使用这个实现,我试图制作一些示例列表。单元素列表很容易制作: let bla_1 = Some {v = 1; next = None; prev = None};; 我猜一个空列表应该是两个无节点。但是我不知道如何创建包含更多元素的列表。如果您想创建

我得到了以下双链接列表的实现:

type 'a elem = {v : 'a; mutable next : 'a lista; mutable prev : 'a lista}
and 'a lista = 'a elem option;;
使用这个实现,我试图制作一些示例列表。单元素列表很容易制作:

let bla_1 = Some {v = 1; next = None; prev = None};;

我猜一个空列表应该是两个无节点。但是我不知道如何创建包含更多元素的列表。

如果您想创建包含两个元素
x
y
的列表,您必须确保有两个类型为
'a elem
的值彼此指向对方(不包括中间选项类型
'a lista
)。最终,您需要有一个圆形结构,其中:

  • lx
    绑定到
    {v=x;next=ly;prev=None}
  • 并且
    ly
    绑定到
    {v=y;next=None;prev=Some lx}
在OCaml中可以有相互递归的值(感谢octhacron):

但这很难用于构建更复杂的列表。这就是为什么您有可变字段:您可以构建节点,然后通过更改它们的
next
prev
字段来连接它们。例如,首先定义
lx
,将
next
字段设置为
None
,只有在知道
ly
是什么之后,才能将
lx.next
所指的值替换为
Some-ly

下面是一个将常规列表转换为双链接列表的函数;当递归调用自身时,它构建节点;从递归调用返回时,它修改
next
节点,使其通过
prev
字段指向当前节点:

let rec to_dbl_list = function
    [] -> None
  | x::xs ->
     let node = { v = x; prev = None ; next = (to_dbl_list xs)} in
     let current = Some node in
     (match node.next with
        None -> ()
      | Some next -> (next.prev <- current)) ;
     current ;;
让rec to_dbl_list=函数
[]->无
|x::xs->
让node={v=x;prev=None;next=(to_dbl_list xs)}in
让current=中的某个节点
(将node.next与
无->()

|一些next->(next.prev如果你想用两个元素
x
y
构建一个列表,你必须确保有两个类型为
'a elem
的值相互指向(不包括中间选项类型
'a lista
)。最终,你需要有一个循环结构,其中:

  • lx
    绑定到
    {v=x;next=ly;prev=None}
  • 并且
    ly
    绑定到
    {v=y;next=None;prev=Some lx}
在OCaml中可以有相互递归的值(感谢octhacron):

但这很难用于构建更复杂的列表。这就是为什么您有可变字段:您可以构建节点,然后通过更改其
next
prev
字段来连接它们。例如,您首先定义
lx
,将
next
字段设置为
None
,并且只有在您知道
ly
,您可以将由
lx指向的值替换为
Some ly

下面是一个将常规列表转换为双链接列表的函数;当递归调用自身时,它构建节点;当从递归调用返回时,它修改
next
节点,以便通过其
prev
字段指向当前节点:

let rec to_dbl_list = function
    [] -> None
  | x::xs ->
     let node = { v = x; prev = None ; next = (to_dbl_list xs)} in
     let current = Some node in
     (match node.next with
        None -> ()
      | Some next -> (next.prev <- current)) ;
     current ;;
让rec to_dbl_list=函数
[]->无
|x::xs->
让node={v=x;prev=None;next=(to_dbl_list xs)}in
让current=中的某个节点
(将node.next与
无->()

|一些下一步->(next.prev这是一个双链接列表:我知道,但我如何制作一个由for.ex3节点1,2,3组成的列表?这是一个双链接列表:我知道,但我如何制作一个由for.ex3节点1,2,3组成的列表?在OCaml中,相互递归的值是完全可能的,但在这种情况下它们确实没有真正的用处:
let rec x={v=0;next=Some y;prev=None}和y={v=1;next=None;prev=Some x}
起作用。@octachron谢谢,我错过了!在OCaml中,相互递归的值是完全可能的,但在这种情况下它们确实没有真正的用处:
让rec x={v=0;next=Some y;prev=None}和y={v=1;next=None;prev=Some x}
有效。@octachron谢谢,我错过了!
# to_dbl_list [1; 2; 3];;
- : int lista =
Some
 {v = 1;
  next =
   Some
    {v = 2; next = Some {v = 3; next = None; prev = <cycle>}; prev = <cycle>};
  prev = None}