im currently building double linked list using Refcell,Weak,Rc Pointer, everything goes well until i have requirement to add a node in the middle of the list.
here is my code so far :
use std::rc::{Rc,Weak};
use std::cell::RefCell;
#[derive(Debug)]
struct Node{
prev:Option<Weak<RefCell<Node>>>,
val:i32,
next:Option<Rc<RefCell<Node>>>,
}
impl Node{
fn new(val:i32)-> Self{
Self{
prev:None,
val:val,
next:None,
}
}
}
#[derive(Debug)]
struct DoubleLinkedList {
head:Option<Rc<RefCell<Node>>>,
tail:Option<Rc<RefCell<Node>>>,
length:i32,
}
impl DoubleLinkedList {
fn new() -> Self {
Self{
head:None,
tail:None,
length:0,
}
}
fn add_at_head(&mut self, val: i32) {
let mut newnode:Rc<RefCell<Node>>=Rc::new(RefCell::new(Node::new(val)));
if self.length==0{
self.head=Some(Rc::clone(&newnode));
self.tail=Some(Rc::clone(&newnode));
}else{
let mut borrownewnode=(newnode.borrow_mut());
let mut borrowhead=(self.head.as_mut().unwrap().borrow_mut());
borrowhead.prev=Some(Rc::downgrade(&newnode));
drop(borrowhead);
borrownewnode.next=self.head.take();
drop(borrownewnode);
self.head=Some(Rc::clone(&newnode));
}
self.length+=1;
}
fn add_at_tail(&mut self, val: i32) {
let mut newnode:Rc<RefCell<Node>>=Rc::new(RefCell::new(Node::new(val)));
if self.length==0{
self.head=Some(Rc::clone(&newnode));
self.tail=Some(Rc::clone(&newnode));
}else{
let mut borrownewnode=(newnode.borrow_mut());
let mut borrowtail=(self.tail.as_mut().unwrap().borrow_mut());
borrowtail.next=Some(Rc::clone(&newnode));
drop(borrowtail);
borrownewnode.prev=Some(Rc::downgrade(self.tail.take().as_ref().unwrap()));
drop(borrownewnode);
self.tail=Some(Rc::clone(&newnode));
}
self.length+=1;
}
fn add_at_index(&mut self,index:i32,val:i32){
if index>self.length{
return
}
let mut current:&Option<Rc<RefCell<Node>>>=&self.head;
if index>0{
for i in 0..index-1{
let borrow=current.as_ref().unwrap().borrow();
current=&borrow.next;
drop(borrow);
}
}
let mut newnode:Rc<RefCell<Node>>=Rc::new(RefCell::new(Node::new(val)));
let mut borrownewnode=newnode.borrow_mut();
/*if self.length==0{
self.head=Some(Rc::clone(&newnode));
self.tail=Some(Rc::clone(&newnode));
}else if index==0{
let mut borrowhead=self.head.as_mut().unwrap().borrow_mut();
borrowhead.prev=Some(Rc::downgrade(&newnode));
drop(borrowhead);
borrownewnode.next=self.head.take();
self.head=Some(Rc::clone(&newnode));
}else if index==self.length{
let mut borrowtail=self.tail.as_mut().unwrap().borrow_mut();
borrowtail.next=Some(Rc::clone(&newnode));
drop(borrowtail);
borrownewnode.prev=Some(Rc::downgrade(self.tail.take().as_ref().unwrap()));
self.tail=Some(Rc::clone(&newnode));
}else{
let mut borrowcur=current.as_mut().unwrap().borrow_mut();
let mut next=borrowcur.next.take();
drop(borrowcur);
println!("{:?} {:?}",next,current);
}
*/
drop(borrownewnode);
self.length+=1;
}
}
let mut mylist:DoubleLinkedList=DoubleLinkedList::new();
mylist.add_at_head(1);
mylist.add_at_head(2);
mylist.add_at_tail(3);
mylist.add_at_index(2,6);
}
my main problem is traversing the linkedlist throught Rc and Refcell , i already try all possible thing i know but nothing still works. and i even doubt if its possible to add node in the middle of double linked list using this method.
main problem:
let mut current:&Option<Rc<RefCell<Node>>>=&self.head;
if index>0{
for i in 0..index-1{
let borrow=current.as_ref().unwrap().borrow();
current=&borrow.next;
drop(borrow);
}
}
want to loop list and get the next Option<Rc<RefCell>> and referenced it