/*
・注意:双方向リストだけど循環参照は未解決のまま
・注意:要素への参照を使っての操作はリスト側には未反映
(front, backを正しく再設定し直したりはしないということ)
(両端の要素の外側に追加したときとかおかしくなるはず)
・手元の1.8.0で主に動作チェック
・基本的によく分かってないので妙な箇所があるはず
・イテレータを提供したかったがよく分からなかったので諦めた
・fmt::Debug for LinkedList<T>は本来はもっとスッキリ書けるはず
・push_prev(&self, h)などが何も返さないのは、selfを返すかhを返すか
どっちを返すのが自然なのかという判断に迷って決め切れなかったため
*/
use std::rc::Rc;
use std::cell::RefCell;
type Handle<T> = Option<Rc<RefCell<Node<T>>>>;
#[derive(PartialEq)]
struct Node<T> {
value: T,
prev: Handle<T>,
next: Handle<T>,
}
impl<T> Node<T> {
fn new(value: T) -> Node<T> {
Node {value: value, prev: None, next: None}
}
}
trait HandleOperation<T> {
fn new(value: T) -> Handle<T>;
fn prev(&self) -> Handle<T>;
fn next(&self) -> Handle<T>;
fn set_value(&self, value: T);
fn set_prev(&self, h: Handle<T>);
fn set_next(&self, h: Handle<T>);
fn push_prev(&self, h: Handle<T>);
fn push_next(&self, h: Handle<T>);
fn pop(&self) -> Handle<T>;
fn pop_prev(&self) -> Handle<T>;
fn pop_next(&self) -> Handle<T>;
fn ptr_eq(this: &Self, other: &Self) -> bool;
}
impl<T> HandleOperation<T> for Handle<T> {
fn new(value: T) -> Handle<T> {
Some(Rc::new(RefCell::new(Node::new(value))))
}
fn prev(&self) -> Handle<T> {
if let Some(rc) = self.as_ref() {rc.borrow().prev.clone()} else {None}
}
fn next(&self) -> Handle<T> {
if let Some(rc) = self.as_ref() {rc.borrow().next.clone()} else {None}
}
fn set_value(&self, value: T) {
if let Some(rc) = self.as_ref() {rc.borrow_mut().value = value;}
}
fn set_prev(&self, h: Handle<T>) {
if let Some(rc) = self.as_ref() {rc.borrow_mut().prev = h;}
}
fn set_next(&self, h: Handle<T>) {
if let Some(rc) = self.as_ref() {rc.borrow_mut().next = h;}
}
fn push_prev(&self, h: Handle<T>) {
if self.is_none() {return;}
self.prev().set_next(h.clone());
h.set_prev(self.prev());
h.set_next(self.clone());
self.set_prev(h);
}
fn push_next(&self, h: Handle<T>) {
if self.is_none() {return;}
self.next().set_prev(h.clone());
h.set_next(self.next());
h.set_prev(self.clone());
self.set_next(h);
}
fn pop(&self) -> Handle<T> {
if self.is_none() {return None;}
self.prev().set_next(self.next());
self.next().set_prev(self.prev());
self.set_prev(None);
self.set_next(None);
self.clone()
}
fn pop_prev(&self) -> Handle<T> {
if self.is_some() {self.prev().pop()} else {None}
}
fn pop_next(&self) -> Handle<T> {
if self.is_some() {self.next().pop()} else {None}
}
fn ptr_eq(this: &Self, other: &Self) -> bool {
match (this.as_ref(), other.as_ref()) {
(Some(ref a), Some(ref b)) => &***a as *const RefCell<_> == &***b as *const RefCell<_>,
(None, None) => true,
_ => false,
}
}
}
use std::fmt;
impl<T: fmt::Debug> fmt::Debug for Node<T> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
//write!(f, "Node {{ value: {:?}}}", self.value)
write!(f, "{:?}", self.value)
}
}
struct LinkedList<T> {
front: Handle<T>,
back: Handle<T>,
}
impl<T> LinkedList<T> {
fn new() -> LinkedList<T> {LinkedList {front: None, back: None}}
fn push_front(&mut self, value: T) -> Handle<T> {
let h = Handle::new(value);
h.push_next(self.front.clone());
self.front = h.clone();
if self.back.is_none() {self.back = h.clone()}
h
}
fn push_back(&mut self, value: T) -> Handle<T> {
let h = Handle::new(value);
h.push_prev(self.back.clone());
self.back = h.clone();
if self.front.is_none() {self.front = h.clone()}
h
}
fn pop_front(&mut self) -> Handle<T> {
let next = self.front.next();
let popped = self.front.pop();
self.front = next;
if Handle::ptr_eq(&popped, &self.back) {self.back = None;}
popped
}
fn pop_back(&mut self) -> Handle<T> {
let prev = self.back.prev();
let popped = self.back.pop();
self.back = prev;
if Handle::ptr_eq(&popped, &self.front) {self.front = None;}
popped
}
fn clear(&mut self) {
while self.front.is_some() {self.pop_front();}
}
}
impl<T: fmt::Debug> fmt::Debug for LinkedList<T> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let mut p = self.front.clone();
let mut v = Vec::new();
while p.is_some() {
v.push(p.clone());
p = p.next();
}
write!(f, "{:?}", v)
}
}
fn main() {
let mut ll = LinkedList::new();
let mut v: Vec<Handle<i32>> = Vec::new();
v.push(ll.push_back(10));
v.push(ll.push_back(20));
println!("{:?}\n{:?}\n", ll, v);
let h = Handle::new(11);
v[1].push_prev(h.clone()); // O(1)での挿入
v.insert(1, h); // O(不明?)でのアクセス用配列のケア
println!("{:?}\n{:?}\n", ll, v);
v[1].set_value(12); // O(1)での値更新
println!("{:?}\n{:?}\n", ll, v);
if let Some(rc) = v[1].as_ref() {rc.borrow_mut().value = 13;} // O(1)でのborrow_mut()
println!("{:?}\n{:?}\n", ll, v);
if let Some(rc) = v[1].as_ref() {println!("borrow().value: {}", rc.borrow().value);} // O(1)でのborrow()
let popped = v[1].pop(); // O(1)での取り外し
v.
remove(1); // O(不明?)でのアクセス用配列のケア println!("popped: {:?}", popped);
println!("{:?}\n{:?}\n", ll, v);
ll.clear(); // 循環参照をケアしてないのでとりあえずこうやって対処
}