Rust 这两种链表实现之间的区别是什么?

Rust 这两种链表实现之间的区别是什么?,rust,Rust,考虑这一实施: pub enum List { Empty, Elem(i32, Box<List>), } struct Node { elem: i32, next: List, } pub enum List { Empty, More(Box<Node>), } 考虑另一个链表实现: pub enum List { Empty, Elem(i32, Box<List>), } st

考虑这一实施:

pub enum List {
    Empty,
    Elem(i32, Box<List>),
}
struct Node {
    elem: i32,
    next: List,
}

pub enum List {
    Empty,
    More(Box<Node>),
}
考虑另一个链表实现:

pub enum List {
    Empty,
    Elem(i32, Box<List>),
}
struct Node {
    elem: i32,
    next: List,
}

pub enum List {
    Empty,
    More(Box<Node>),
}

这两种内存布局非常相似,我真的不知道第二种实现如何比第一种更好,因为第二种布局实际上是两种

[Moreptr]->元素A,元素R->元素B,空 或

[元素A,更多]->元素B,空
空元素没有堆分配。

第二个布局实际上是

[Moreptr]->元素A,元素R->元素B,空 或

[元素A,更多]->元素B,空
空元素没有堆分配。

由于此示例取自此示例,因此我仅引用:

有两个关键问题:

我们分配的节点只是说我实际上不是节点 我们的一个节点根本没有分配。 从表面上看,这两者似乎相互抵消。我们分配了一个额外的节点,但其中一个节点根本不需要分配。然而,考虑下面的潜在布局我们的列表:

[ptr] -> (Elem A, ptr) -> (Elem B, *null*)
在这个布局中,我们现在无条件地堆分配节点。关键的区别在于我们的第一个布局中没有垃圾

[……]

这里最大的收获是,即使空是一个信息位,它也必须为指针和元素消耗足够的空间,因为它必须随时准备成为元素。因此,第一个布局堆分配了一个额外的元素,该元素充满了垃圾,比第二个布局占用更多的空间

也许令人惊讶的是,我们的一个根本没有被分配的节点也比总是分配它更糟糕。这是因为它为我们提供了一个非统一的节点布局。这对推送和弹出节点没有太大影响,但对拆分和合并列表确实有影响

[……]

链表为数不多的优点之一是,您可以在节点本身中构造元素,然后在列表中自由移动它,而无需移动它。你只是摆弄指针,东西就会被移动。布局1将刷新此属性

这只是其中的一些关键点。事实上,我认为该书作者给出的解释在提供适当的推理以及从第一次迭代到下一次迭代所涉及的思考过程方面非常出色


我建议你重读整章,确保你理解其中的要点。如果你对个别陈述有明确的问题,你可以具体询问。

因为这个例子就是从这个例子中摘取的,所以我只引用:

有两个关键问题:

我们分配的节点只是说我实际上不是节点 我们的一个节点根本没有分配。 从表面上看,这两者似乎相互抵消。我们分配了一个额外的节点,但其中一个节点根本不需要分配。然而,考虑下面的潜在布局我们的列表:

[ptr] -> (Elem A, ptr) -> (Elem B, *null*)
在这个布局中,我们现在无条件地堆分配节点。关键的区别在于我们的第一个布局中没有垃圾

[……]

这里最大的收获是,即使空是一个信息位,它也必须为指针和元素消耗足够的空间,因为它必须随时准备成为元素。因此,第一个布局堆分配了一个额外的元素,该元素充满了垃圾,比第二个布局占用更多的空间

也许令人惊讶的是,我们的一个根本没有被分配的节点也比总是分配它更糟糕。这是因为它为我们提供了一个非统一的节点布局。这对推送和弹出节点没有太大影响,但对拆分和合并列表确实有影响

[……]

链表为数不多的优点之一是,您可以在节点本身中构造元素,然后在列表中自由移动它,而无需移动它。你只是摆弄指针,东西就会被移动。布局1将刷新此属性

这只是其中的一些关键点。事实上,我认为该书作者给出的解释在提供适当的推理以及从第一次迭代到下一次迭代所涉及的思考过程方面非常出色

我建议你重读整章,确保你理解其中的要点。如果你对个别陈述有明确的问题,你可以具体询问