【问题标题】:Definition of tree structure in LispLisp中树结构的定义
【发布时间】:2014-09-23 00:18:20
【问题描述】:

来自 Common Lisp HyperSpec 词汇表:

treen。 1. 由 conses 和 原子:conses 本身也是树(有时称为 “子树”或“分支”),原子是终端节点(有时 称为叶子)。通常,叶子代表数据,而 分支在该数据之间建立某种关系。 2. 一般来说, 任何具有“分支”概念的递归数据结构和 树叶。

tree structuren。 (一棵树)组成树的一组cons。 请注意,虽然每个此类 cons 的 car[1b] 组件都是 树结构,对象是树中每个缺点的汽车 本身不是其树结构的一部分,除非它们也是 缺点。

树结构定义中的最后一句话提出了一个问题,那就是cdrs也可以这样说吗?

在“树”的定义中使用二进制这个词似乎表明 car 与 cdr 对于树的目的没有区别,但是“树结构”的定义似乎对汽车进行了特殊处理,所以我我很困惑。

【问题讨论】:

    标签: tree lisp common-lisp


    【解决方案1】:

    简答

    树结构定义中的最后一句话提出了一个 问题,也就是说,cdrs 也可以这样说吗?

    我认为答案是“是的”。 列表结构 有一个类似的定义,其措辞几乎相同。在列表结构中,关于 cons 的 car 的值是否是列表结构的一部分,存在更多混淆的可能性,因为可能会出现问题,例如,“在列表中替换 X 意味着什么(X (X)是)?” cdr 并没有太大的问题,因为 cdr 是列表的 rest ;它显然是列表结构的一部分。

    对于树形结构,我认为歧义较少;汽车或 cdr 中的缺点是子树。 树结构列表结构的定义在某些地方几乎相同,如果有人写了列表结构的定义,我不会感到惊讶,然后将其复制为 树形结构,从而实现准确所需的最少更改。即使它所回答的问题在实践中可能不会出现,这也会留下一些关于汽车的信息。

    更长的答案

    我们看看列表结构的定义,对比一下:

    list structuren。 (列表的)组成列表的一组cons。 请注意,虽然每个此类缺点的汽车组件都是 列表结构,作为列表元素的对象(即 列表中每个缺点的汽车的对象)不是 它们本身是其列表结构的一部分,即使它们是 cons,除了 在(循环)情况下,列表实际上包含其中一个 尾巴作为一个元素。 (列表的列表结构有时是 按顺序冗余地称为其“顶级列表结构” 强调作为列表元素的任何 conses 不是 参与。)

    注意这些不同的具体地方:

    (列表结构)请注意,虽然每个此类 cons 的 car 组件都是 列表结构,作为列表元素的对象(即 列表中每个缺点的汽车的对象)不是 它们本身是其列表结构的一部分,即使它们是 conses。

    (树结构)请注意,虽然每个此类 cons 的 car 组件都是 树结构,对象是树中每个缺点的汽车 本身不是其树结构的一部分,除非它们也是 缺点。

    这意味着在

    (1 (2) 3) == (cons 1 (cons (cons 2 nil) (cons 3 nil)))
    

    列表结构中有三个个cons单元,树结构中有四个个cons单元。

    这实际上在哪里重要?准确定义这些术语变得很重要,这样规范才能轻松定义特定函数遍历或修改列表或树的哪些部分。

    nsubst 可以修改树形结构

    例如,函数nsubst and friends,其文档指出:

    nsubst、nsubst-if 和 nsubst-if-not 可能会改变 tree structure 的 树。

    树结构的具体定义让我们了解nsubst可能改变和不可能改变的事物。

    tree structuren。 (一棵树)组成树的一组cons。 请注意,虽然每个此类缺点的汽车组件都是 树结构,对象是树中每个缺点的汽车 本身不是其树结构的一部分,除非它们也是 缺点。

    所以,这告诉我们的是,对于树中的任何 cons 单元 xnsubst 可能会执行 (setf (car x) ...),因此 (car x) 稍后可能会有所不同,但它不会修改 (car x) 将返回的实际对象(当然,除非这是一个缺点)。这在 (car x) 的值是一个内部可能有树的对象的情况下可能很重要。例如,nsubst 不会下降到向量,但会替换向量:

    (let* ((l (list 1 2 3))     ; a list
           (v (vector 0 l 4))   ; a vector that contains the list (and other elements)
           (tree (cons l v)))   ; a tree containing the list and the vector
      (nsubst 'x l tree))       ; replace the list in the tree with X
    ;=> (X . #(0 (1 2 3) 4))    ; nsubst doesn't descend into the vector, because it's
                                ; not tree structure
    

    delete-duplicates 可以修改列表结构

    另一方面,delete-duplicates 只会修改列表结构:

    delete-duplicates,当序列是一个列表时,允许设置任何 该序列中顶级列表结构的一部分 car 或 cdr。 当序列是一个向量时,delete-duplicates 被允许改变 矢量的尺寸并将其元素滑入新的 位置而不用置换它们来产生结果向量。

    【讨论】:

      【解决方案2】:

      请注意,虽然每个此类 cons 的 car[1b] 组件是 树结构,对象是树中每个缺点的汽车 本身不是其树结构的一部分,除非它们也是 缺点。

      据我所知,这个定义的作者试图在树本身的结构和它的对象之间划清界限。所以它指出只有 conses 才能构成树的结构。

      考虑这个例子:

      (1 2 (3 "string") 4)
      

      虽然对象 "string" 是树的一部分(它是 ("string")car),但它不是树结构的一部分,因为字符串不包含 cons 单元格。

      我想定义的作者已经想到了正确的列表,因为对他们来说每个元素都是car

      (cons "foo" (cons "bar" (cons "baz" nil)))
      ;     ^car^       ^car^       ^car^
      

      cdr 而是在正确列表的情况下定义树的结构。

      但您也可以将以下内容视为树:

      ("foo" . "bar")
      

      在这种情况下,cdr 不会是树结构的一部分。

      【讨论】:

      • 我想定义的作者想到了适当的列表我不认为是这样。词汇表还定义了 list 结构,其中列表的元素是列表结构的 conses 的汽车。我认为包含这些术语主要是为了明确哪些结构被遍历并且可以被标准函数修改。例如,如果在树 (X (X) #(X))) 中将 X 替换为 Y,则会得到 (Y (Y) #(X))),但是如果你在列表中替换 (X (X) #(X))),你会得到 (Y (X) #(X)))。用树/列表结构来描述修改是最容易的。
      • @Joshua,好吧,OP 的问题是:“可以相同(car 每个 cons 的组件是树结构的一部分,树中每个 cons 的汽车的对象不是它们本身是其树结构的一部分)也可以说是 cdrs”。所以在我的回答中,我关注carcdr 在树结构中的区别。在适当的列表(以及树)中,每个对象(原子)总是 car 的缺点,我认为这就是定义作者强调汽车的原因。
      • @Joshua,我只是不明白为什么定义的作者对cdrs 的陈述不一样。我可能错了。
      • 这很好。不过,老实说,如果将其中一个术语的定义写出来(可能是列表的定义),然后对另一个术语进行最少的编辑,我不会感到惊讶。措辞几乎相同,并且正如您所说,由于列表的 cdr 是列表结构的一部分是一种 明显,因此只有“子列表” in the car 是有问题的列表结构的一部分。因此,虽然我认为“我认为定义的作者考虑到了适当的列表”并不完全正确,但很可能是“定义强调这一点,因为它......
      • …基于类似的列表定义,强调汽车更有意义。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多