使用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