rust编程-智能指针:实现单链表、共享链表、双链表

使用Box实现单链表

#[derive(Debug)]
struct Node{
    value : i32,
    next : Box<Option<Node>>,
}

fn main(){
    let a = Node{
        value : 1,
        next : Box::new(None),
    };
    let b = Node{
        value : 2,
        next : Box::new(Some(a)), //a已经被移动了
    };
    println!("b is {:?}",b);
}

输出结果为:

b is Node { value: 2, next: Some(Node { value: 1, next: None }) }

注:C++中与Box等价的是unique pointer。

使用Rc实现共享链表

共享链表指的是两个或以上的链表共享一个或多个节点,所以有的节点需要有多个所有者。Rc通过clone来共享。

#[derive(Debug)]
struct ShareNode{
    value : i32,
    next : Rc<Option<ShareNode>>,
}

use std::rc::Rc;

fn main(){
    let a = Rc::new(Some(ShareNode{
        value : 1,
        next : Rc::new(None),
    }));
    println!("引用计数为:{}",Rc::strong_count(&a));
    let b = ShareNode{
        value : 2,
        next : Rc::clone(&a),
    };
    println!("b is {:?}",b);
    println!("引用计数为:{}",Rc::strong_count(&a));
}

输出结果为:

引用计数为:1
b is ShareNode { value: 2, next: Some(ShareNode { value: 1, next: None }) }
引用计数为:2

注:C++中与Rc等价的是shared pointer。

使用RefCell实现变更

针对上面的Box和Rc例子,使用RefCell可实现内部可变性。

#[derive(Debug)]
struct Node{
    value : i32,
    next : Box<RefCell<Option<Node>>>,
}

#[derive(Debug)]
struct ShareNode{
    value : i32,
    next : Rc<RefCell<Option<ShareNode>>>,
}

use std::cell::RefCell;
use std::rc::Rc;

fn main(){
//Box
    println!("====Box====");
    let a = Node{
        value : 1,
        next : Box::new(RefCell::new(None)),
    };
    let b = Node{
        value : 2,
        next : Box::new(RefCell::new(Some(a))),
    };
    println!("Node b is {:?}",b);
    //RefCell<T>提供的borrow_mut()函数返回一个可变的智能指针RefMut<T>,也就是x,通过*可以解引用
    //要注意的是,同一个作用域使用多个RefMut<T>的话会造成panic,因为可变引用只能有一个
    if let Some(ref mut x) = *b.next.borrow_mut(){ //只能改变b的下一个节点的值
        (*x).value += 2;
        //x.value += 2;//这种写法和上面的输出结果一致
    }
    println!("Node b is {:?}",b);
    
//Rc   
    println!("====Rc====");
    let a = Rc::new(RefCell::new(Some(ShareNode{
        value : 1,
        next : Rc::new(RefCell::new(None)),
    })));
    let b = ShareNode{
        value : 2,
        next : Rc::clone(&a),
    };
    println!("ShareNode a is {:?}",a);
    println!("ShareNode b is {:?}",b);
    if let Some(ref mut x) = *a.borrow_mut(){ //只能改变a
        (*x).value += 2;
    }
    println!("ShareNode a is {:?}",a);
    println!("ShareNode b is {:?}",b);
}

输出结果为:

====Box====
Node b is Node { value: 10, next: RefCell { value: Some(Node { value: 2, next: RefCell { value: Some(Node { value: 1, next: RefCell { value: None } }) } }) } }
Node b is Node { value: 10, next: RefCell { value: Some(Node { value: 4, next: RefCell { value: Some(Node { value: 1, next: RefCell { value: None } }) } }) } }
====Rc====
ShareNode a is RefCell { value: Some(ShareNode { value: 1, next: RefCell { value: None } }) }
ShareNode b is ShareNode { value: 2, next: RefCell { value: Some(ShareNode { value: 1, next: RefCell { value: None } }) } }
ShareNode a is RefCell { value: Some(ShareNode { value: 3, next: RefCell { value: None } }) }
ShareNode b is ShareNode { value: 2, next: RefCell { value: Some(ShareNode { value: 3, next: RefCell { value: None } }) } }

使用Weak实现可变的双链表

Rc无法实现双链表,因为两个节点互相指向对方的话会造成栈溢出。weak pointer持有一个对象的非拥有引用,类似于Rc,但不会影响析构。

#[derive(Debug)]
struct DoubleNode{
    value : i32,
    next : Rc<RefCell<Option<DoubleNode>>>,
    prev : Weak<RefCell<Option<DoubleNode>>>,
}

use std::cell::RefCell;
use std::rc::{Rc,Weak};

fn main(){
    let a = Rc::new(RefCell::new(Some(DoubleNode{
        value : 1,
        next : Rc::new(RefCell::new(None)),
        prev : Weak::new(),
    })));
    let b = Rc::new(RefCell::new(Some(DoubleNode{
        value : 2,
        next : Rc::clone(&a),
        prev : Weak::new(),
    })));
    if let Some(ref mut x) = *a.borrow_mut(){
        (*x).prev = Rc::downgrade(&b);
    }
    println!("DoubleNode a is {:?},强引用个数为:{},弱引用个数为:{}",a,Rc::strong_count(&a),Rc::weak_count(&a));
    println!("DoubleNode b is {:?},强引用个数为:{},弱引用个数为:{}",b,Rc::strong_count(&b),Rc::weak_count(&b));
    
}

输出结果为:

DoubleNode a is RefCell { value: Some(DoubleNode { value: 1, next: RefCell { value: None }, prev: (Weak) }) },强引用个数为:2,弱引用个数为:0
DoubleNode b is RefCell { value: Some(DoubleNode { value: 2, next: RefCell { value: Some(DoubleNode { value: 1, next: RefCell { value: None }, prev: (Weak) }) }, prev: (Weak) }) },强引用个数为:1,弱引用个数为:1

Rust与智能指针

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值