如何理解 rust 的单向链表

注:自我理解 , 详见rust丛书: 《rust语言圣经》
这里我们简单来实现一个单向链表 。
单向链表(单链表)是链表的一种 , 其特点是链表的链接方向是单向的 , 对链表的访问要通过顺序读取从头部开始;链表是使用指针进行构造的列表;又称为结点列表 , 因为链表是由一个个结点组装起来的;其中每个结点都有指针成员变量指向列表中的下一个结点;
链表是由结点构成 , head指针指向第一个成为表头结点 , 而终止于最后一个指向NULL的指针 。
因此取一个单项链表的元素的时间复杂度是On , 但是取最后一个元素的时间复杂度是O1 。
然而链表有特殊的优点就是 , 插入数据快 , 可以随意插入到中间节点(数组的插入往往涉及到后面元素的拷贝 , 如果超过容量长度也会涉及到拷贝) , 同理 , 删除也是非常快 , 只需要将上一个链接的头跳过某个元素指向下一个 , 这就实现了删除 , 等等
正常来说 , 我们会有以下变量: 链表对象List , 头:Head , 节点:Node
一个List , 有一个Head , Head指向一个Node , 为了形成一个链 , 这个Node , 还会指向下一个Node
由于链表中是需要保存数据的 , 因此数据是需要保存在节点中的 , 因此节点Node中不仅包含下一个元素next , 还包含数据本身value(这里我们就只存一个数字 , 比如:i32 , 未来可以做成一个泛型T或者使用trait bound保存更多更丰富的数据)
好的 , 那就开始:
第一步定义节点对象:Node
// 首先准备一个Node对象// struct Node {//value: i32,//next: ??,// }// 这个next需要指向下一个Node , 因此next// struct Node {//value: i32,//next: Node,// }// 这么写会发现 , 会报错:recursive type `Node` has infinite size// 提示你Node外面要包一层比如Box , 也就是智能指针 , 这样存储就不会导致无法计算需要多少内存了 , // 因为指针在栈上的内存确定的 , 就是8个字节(64位系统)struct Node {value: i32,next: Box,}// 接下来你想想 , 这个next有2中可能 , 一种是存在一个Node , 一个是不存在一个Node , rust中是不允许指向一个空的// 因此很容易 , 外面再包一层Option即可 , 有值就是Node , 没值就是None,这很容易理解的
因此 , 最终Node的定义如下:
struct Node {value: i32,next: Option,}
第二步 , 定义链表:List
// struct List {//head: Node,// }// 看到上面定义的List , 你是不是突然想起来 , 刚刚定义Node的时候 , 指向下一个Node , 要包2层东西// 一层用来确定指向的Node不是空 , 一层是用来指向Node本身的指针 , 也就是一个取Point// 因此我们这里也同样的包一下 , 原因还是和上面的一样struct List {head: Option,}// 因为我们知道 , rust中是可以将某个长类型提取出来的 , 比如:type Next = Option;
因此最终定义如下:
type Next = Option;struct List {size: u32, // 这里是为了配合查询链表长度添加的字段 , 如果没有这个功能 , 可以不要该属性head: Next,}struct Node {value: i32,next: Next,}