用链表学Rust | A Bad Stack

一个好朋友推荐的书籍, 趁着感恩节假期学习一下! 原文在这里, 网上可以找到很多中文版翻译, 某站上有讲解视频, 不过我没太看过, 不好评价。这个笔记是我学习过程中的一些记录和心得, 欢迎大家指正!有些名词我不知道标准的翻译, 直接使用英文, 包括: list, node, layout…

A Bad Stuck

首先复习函数式编程中list的概念, 递归定义的list属于 sum type, 类比C语言中的enumList a = Empty | Elem a (List a)
第一次尝试:

pub enum List {
   
    Empty,
    Elem(i32, List),
}

编译错误!解决方案:引入Box确定分配在堆上的空间大小, Box是管理堆分配的指针类型。

#[derive(Debug)]
pub enum List {
   
    Empty,
    Elem(i32, Box<List>),
}

以包含两个元素A, B的list为例, 实际的空间分配情况如下。

[] = Stack
() = Heap

[Elem A, ptr] -> (Elem B, ptr) -> (Empty, *junk*)

注意:用Box分配在堆上, 第一个元素A分配在栈上(以Elem(A, Box<List>)的形式), 第一个元素B就嵌套在A的Box<List>里了, 所以分配在堆上, 最后一个元素Empty只能带着*junk*. 这样做的缺点: (1) Empty根本不是一个node; (2) 有的元素在堆上,有的在栈上, 不统一. 改进方案如下:

[ptr] -> (Elem A, ptr) -> (Elem B, *null*)

这个layout解决了上面的两个问题! Empty不再作为单独的node, 所有元素都在堆上了! 第一种情况中Empty所在node要时刻准备着, 预留足够的空间给随时可能到来的新元素.

list的拆分和合并可以引发更多问题.

layout 1:

[Elem A, ptr] -> (Elem B, ptr) -> (Elem C, ptr) -> (Empty *junk*)

split off C:

[Elem A, ptr] -> (Elem B, ptr) -> (Empty *junk*)
[Elem C, ptr] -> (Empty *junk*)

layout 2:

[ptr] -> (Elem A, ptr) -> (Elem B, ptr) -> (Elem C, *null*)

split off C:

[ptr] -> (Elem A, ptr) -> (Elem B, *null*)
[ptr] -> (Elem C, *null*)

比较两个layout, 可以发现layout 1毁掉了list本该拥有的移动指针即可调换元素位置的优点, 和layout 2相比较增加了把元素C从堆复制到栈的过程, 是一个

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值