当前位置: 首页 > 知识库问答 >
问题:

用尾指针写链表的惯用方法是什么?

齐阎宝
2023-03-14

作为Rust的一个学习项目,我有一个非常简单的单链表实现(如果不完整,也可以使用)。结构的声明如下所示:

type NodePtr<T> = Option<Box<Node<T>>>;

struct Node<T> {
    data: T,
    next: NodePtr<T>,
}

pub struct LinkedList<T> {
    head: NodePtr<T>,
}

实施sizepush_front都是相当直接的,尽管反复实施size确实涉及到一些“与借阅检查人的斗争”

我想尝试的下一件事是向LinkedList结构添加一个尾部指针。以启用有效的push_back操作。在这里,我碰到了一堵墙。起初我试图使用选项

从那以后,我得出了一个初步的结论,这些定义是不可能的:没有办法向编译器保证尾巴在我认为有效的地方是有效的。我唯一能做到这一点的方法是让我所有的指针都是Rc

我的问题:这是正确的结论吗?更一般地说:数据结构中无主指针的惯用解决方案是什么?在我看来,对于这么简单的事情来说,引用计数似乎非常重要,所以我想我一定错过了什么。(或者我只是还没有进入记忆安全的正确思维模式。)


共有1个答案

夏朝
2023-03-14

是的,如果你想写一个带尾部指针的单链表,你有三个选择:

  • 安全且可变:使用NodePtr=选项

*mut将更有效,而且它不像Rc实际上会阻止你产生完全无意义的状态(正如你正确推断的那样)。它只是要保证它们不会导致SEGFULTS(而对于RefCell,它仍然可能导致运行时崩溃…)。

最终,任何比香草单链接更复杂的链表都有一个过于复杂的所有权故事,无法安全有效地编码到Rust的所有权系统中(它不是树)。我个人倾向于在这一点上接受不安全,并依靠单元测试来完整地到达终点线(为什么要编写一个次优的数据结构...?)。

 类似资料:
  • 问题内容: 我来自没有显式指针的语言,因此我不太了解它们的存在重点(无双关语)。 问题是,在大多数情况下,我不知道为什么要传递指向函数的指针。我确实知道,当您传递一个指针时,到处都会对该变量进行修改,但这有什么意义呢?为什么不修改值并返回结果呢? 例如,是一个函数,该函数接收和作为参数。我读过接口实际上是指针(是吗?),但是我没有得到的是为什么? 为什么我要指向作家?我没有修改它,只是在写它。而且

  • 我试图表示一个简化的染色体,它由N个碱基组成,每个碱基只能是中的一个。 我想用枚举形式化约束,但我想知道在Go中模拟枚举的最惯用的方式是什么。

  • 本文向大家介绍什么是指向指针的指针? 相关面试题,主要包含被问及什么是指向指针的指针? 时的应答技巧和注意事项,需要的朋友参考一下 指针指向的变量是一个指针,即具体内容为一个指针的值,是一个地址. 此时指针指向的变量长度也是4位.

  • 我正在用C语言创建一个单链表,它有头部和尾部指针,其中头部指针指向SLL的起始节点,尾部指针指向SLL的最后一个节点。我不想使用head指针遍历到列表末尾来删除节点。有没有办法让我可以使用尾指针删除SLL的最后一个元素? 下面是节点添加函数。头部和尾部初始化为NULL。 要删除第一个节点,使用以下函数:

  • 所以我有一个堆栈,它允许典型的Push和Pop函数。我很难理解这一切实际上是如何在代码方面工作的。我在这里看到了这篇文章,最佳答案中的图片/图表,展示了列表是如何被“推”下来的,你指向最新的元素。我有一个 它挂接到结构“节点” 我如何结合一个推拉与"节点*下一步;"?最难理解的是我将如何真正做到这一点。我知道它最初指向空,然后如果我推一个2,4,6,它将是6,4,2,#。掌握如何实际使用链表中的指

  • 假设我想要一个使用范围的有限循环: 编译器将发出警告: 有没有更惯用的方法来写这个,不会让编译器抱怨?