Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/logging/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
OCaml中的双端队列-what';什么主意?_Ocaml_Deque_Imperative Programming - Fatal编程技术网

OCaml中的双端队列-what';什么主意?

OCaml中的双端队列-what';什么主意?,ocaml,deque,imperative-programming,Ocaml,Deque,Imperative Programming,我遇到了一个deque的实现: type 'a elem = { mutable l1 : 'a elem; mutable l2 : 'a elem; v : 'a option } type 'a queue = { mutable front : 'a elem; mutable back : 'a elem } let init () = let rec g1 = { l1 = g1; l2 = g2; v = None} and g2 = { l1 = g2;

我遇到了一个deque的实现:

type 'a elem = { mutable l1 : 'a elem; mutable l2 : 'a elem; v : 'a option }
type 'a queue = { mutable front : 'a elem; mutable back : 'a elem }

let init () =
    let rec g1 = { l1 = g1; l2 = g2; v = None}
    and     g2 = { l1 = g2; l2 = g1; v = None}
    in
        { front = g1; back = g2 }

let is_empty q =
    let f = q.front
    and b = q.back
    in
        f.l2 == b

let put_between p q x =
    let r = { l1 = p; l2 = q; v = Some x }
    in begin
        if p.l1 == q then p.l1 <- r else p.l2 <- r;
        if q.l1 == p then q.l1 <- r else q.l2 <- r
    end
type'a elem={mutable l1:'a elem;mutable l2:'a elem;v:'a option}
键入'a queue={mutable front:'a elem;mutable back:'a elem}
设init()=
设rec g1={l1=g1;l2=g2;v=None}
g2={l1=g2;l2=g1;v=None}
在里面
{前面=g1;后面=g2}
让它是空的=
设f=q
b=q.back
在里面
f、 l2==b
让我们把_放在pqx之间=
设r={l1=p;l2=q;v=somex}
开始

如果p.l1==q,那么p.l1稍微扩展一下@Lee所说的内容,这是一个双端队列(或deque)的简单易变实现,就像用普通指针(如C)编写的语言一样

除了保持链接笔直外,我只能看到一些具体的想法

  • deque的每一端都有一个标题(@Lee称之为哨兵)。所以一个空的deque中有两个节点。由于双向链接,每个节点指向另一个节点。(这可能就是您所指的递归。)

  • 因为OCaml是强类型的,所以所有节点都必须是相同的类型,甚至是末尾的头。由于标题中没有值,因此需要对值使用
    'a选项
    。换句话说,您需要允许节点中没有值

  • put\u-between
    的调用者需要提供两个相邻的节点,但它们可以按任意顺序提供

  • 代码使用“物理相等”(
    ==
    )来测试节点的标识。在OCaml中这样做是危险的,但在这里是正确的。可以将可变值与
    ==
    进行比较,或多或少会得到命令式语言中比较指针的结果


  • 学习OCaml的一个原因是学习函数式编程。这段代码对此没有用处,因为(正如我所说)它是一个可变的实现。您可以在的第5章中看到一些实际的功能性deque实现。(你也可以买他的书,这是他长期以来的最爱。)

    它看起来像一个有两个前哨节点的双链接列表。虽然这两种记录类型不是相互递归的-
    elem
    是递归的,但没有引用
    队列
    。但是为什么我们要使用四个链接:
    front.l1
    front.l2
    back.l1
    back.l2
    。在纯C(++)中,您只需使用两个指针-指向下一个和上一个元素每个节点都有两个其他节点:
    l1
    l2
    。有两个链接,而不是四个。队列对象(
    'A queue
    )包含两个头,因此队列对象内总共有四个链接。Aaaa、so
    front
    back
    是虚拟对象,
    l1
    是前一个节点,
    l2
    是下一个节点?是的,这是正确的。我不会称它们为“虚拟”对象,但它们是空节点。使用头稍微简化了代码,特别是在OCaml中,它具有强大的类型。(一个空的deque必须与其中包含一些节点的deque类型相同。)好吧,但是这里有一些奇怪的东西。前一个
    back
    元素是
    back
    本身,下一个
    元素是
    front
    。背后有什么逻辑吗?