mirror of
https://github.com/rust-lang/rust.git
synced 2025-04-08 10:07:27 +00:00
Convert dlist records into structs
This commit is contained in:
parent
339618a7f9
commit
11fd2beef9
@ -28,28 +28,26 @@ use option::{None, Option, Some};
|
|||||||
use option;
|
use option;
|
||||||
use vec;
|
use vec;
|
||||||
|
|
||||||
type DListLink<T> = Option<DListNode<T>>;
|
pub type DListLink<T> = Option<@DListNode<T>>;
|
||||||
|
|
||||||
enum DListNode<T> = @{
|
pub struct DListNode<T> {
|
||||||
data: T,
|
data: T,
|
||||||
mut linked: bool, // for assertions
|
mut linked: bool, // for assertions
|
||||||
mut prev: DListLink<T>,
|
mut prev: DListLink<T>,
|
||||||
mut next: DListLink<T>
|
mut next: DListLink<T>,
|
||||||
};
|
}
|
||||||
|
|
||||||
pub enum DList<T> {
|
pub struct DList<T> {
|
||||||
DList_(@{
|
|
||||||
mut size: uint,
|
mut size: uint,
|
||||||
mut hd: DListLink<T>,
|
mut hd: DListLink<T>,
|
||||||
mut tl: DListLink<T>
|
mut tl: DListLink<T>,
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
priv impl<T> DListNode<T> {
|
priv impl<T> DListNode<T> {
|
||||||
pure fn assert_links() {
|
pure fn assert_links(@self) {
|
||||||
match self.next {
|
match self.next {
|
||||||
Some(neighbour) => match neighbour.prev {
|
Some(neighbour) => match neighbour.prev {
|
||||||
Some(me) => if !managed::ptr_eq(*self, *me) {
|
Some(me) => if !managed::ptr_eq(self, me) {
|
||||||
fail ~"Asymmetric next-link in dlist node."
|
fail ~"Asymmetric next-link in dlist node."
|
||||||
},
|
},
|
||||||
None => fail ~"One-way next-link in dlist node."
|
None => fail ~"One-way next-link in dlist node."
|
||||||
@ -58,7 +56,7 @@ priv impl<T> DListNode<T> {
|
|||||||
}
|
}
|
||||||
match self.prev {
|
match self.prev {
|
||||||
Some(neighbour) => match neighbour.next {
|
Some(neighbour) => match neighbour.next {
|
||||||
Some(me) => if !managed::ptr_eq(*me, *self) {
|
Some(me) => if !managed::ptr_eq(me, self) {
|
||||||
fail ~"Asymmetric prev-link in dlist node."
|
fail ~"Asymmetric prev-link in dlist node."
|
||||||
},
|
},
|
||||||
None => fail ~"One-way prev-link in dlist node."
|
None => fail ~"One-way prev-link in dlist node."
|
||||||
@ -70,24 +68,24 @@ priv impl<T> DListNode<T> {
|
|||||||
|
|
||||||
impl<T> DListNode<T> {
|
impl<T> DListNode<T> {
|
||||||
/// Get the next node in the list, if there is one.
|
/// Get the next node in the list, if there is one.
|
||||||
pure fn next_link() -> Option<DListNode<T>> {
|
pure fn next_link(@self) -> DListLink<T> {
|
||||||
self.assert_links();
|
self.assert_links();
|
||||||
self.next
|
self.next
|
||||||
}
|
}
|
||||||
/// Get the next node in the list, failing if there isn't one.
|
/// Get the next node in the list, failing if there isn't one.
|
||||||
pure fn next_node() -> DListNode<T> {
|
pure fn next_node(@self) -> @DListNode<T> {
|
||||||
match self.next_link() {
|
match self.next_link() {
|
||||||
Some(nobe) => nobe,
|
Some(nobe) => nobe,
|
||||||
None => fail ~"This dlist node has no next neighbour."
|
None => fail ~"This dlist node has no next neighbour."
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/// Get the previous node in the list, if there is one.
|
/// Get the previous node in the list, if there is one.
|
||||||
pure fn prev_link() -> Option<DListNode<T>> {
|
pure fn prev_link(@self) -> DListLink<T> {
|
||||||
self.assert_links();
|
self.assert_links();
|
||||||
self.prev
|
self.prev
|
||||||
}
|
}
|
||||||
/// Get the previous node in the list, failing if there isn't one.
|
/// Get the previous node in the list, failing if there isn't one.
|
||||||
pure fn prev_node() -> DListNode<T> {
|
pure fn prev_node(@self) -> @DListNode<T> {
|
||||||
match self.prev_link() {
|
match self.prev_link() {
|
||||||
Some(nobe) => nobe,
|
Some(nobe) => nobe,
|
||||||
None => fail ~"This dlist node has no previous neighbour."
|
None => fail ~"This dlist node has no previous neighbour."
|
||||||
@ -96,24 +94,23 @@ impl<T> DListNode<T> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Creates a new dlist node with the given data.
|
/// Creates a new dlist node with the given data.
|
||||||
pub pure fn new_dlist_node<T>(data: T) -> DListNode<T> {
|
pub pure fn new_dlist_node<T>(data: T) -> @DListNode<T> {
|
||||||
DListNode(@{data: move data, mut linked: false,
|
@DListNode { data: data, linked: false, prev: None, next: None }
|
||||||
mut prev: None, mut next: None})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Creates a new, empty dlist.
|
/// Creates a new, empty dlist.
|
||||||
pub pure fn DList<T>() -> DList<T> {
|
pub pure fn DList<T>() -> @DList<T> {
|
||||||
DList_(@{mut size: 0, mut hd: None, mut tl: None})
|
@DList { size: 0, hd: None, tl: None }
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Creates a new dlist with a single element
|
/// Creates a new dlist with a single element
|
||||||
pub pure fn from_elem<T>(data: T) -> DList<T> {
|
pub pure fn from_elem<T>(data: T) -> @DList<T> {
|
||||||
let list = DList();
|
let list = DList();
|
||||||
unsafe { list.push(move data); }
|
unsafe { list.push(data); }
|
||||||
list
|
list
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn from_vec<T: Copy>(vec: &[T]) -> DList<T> {
|
pub fn from_vec<T: Copy>(vec: &[T]) -> @DList<T> {
|
||||||
do vec::foldl(DList(), vec) |list,data| {
|
do vec::foldl(DList(), vec) |list,data| {
|
||||||
list.push(*data); // Iterating left-to-right -- add newly to the tail.
|
list.push(*data); // Iterating left-to-right -- add newly to the tail.
|
||||||
list
|
list
|
||||||
@ -122,7 +119,7 @@ pub fn from_vec<T: Copy>(vec: &[T]) -> DList<T> {
|
|||||||
|
|
||||||
/// Produce a list from a list of lists, leaving no elements behind in the
|
/// Produce a list from a list of lists, leaving no elements behind in the
|
||||||
/// input. O(number of sub-lists).
|
/// input. O(number of sub-lists).
|
||||||
pub fn concat<T>(lists: DList<DList<T>>) -> DList<T> {
|
pub fn concat<T>(lists: @DList<@DList<T>>) -> @DList<T> {
|
||||||
let result = DList();
|
let result = DList();
|
||||||
while !lists.is_empty() {
|
while !lists.is_empty() {
|
||||||
result.append(lists.pop().get());
|
result.append(lists.pop().get());
|
||||||
@ -131,11 +128,10 @@ pub fn concat<T>(lists: DList<DList<T>>) -> DList<T> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
priv impl<T> DList<T> {
|
priv impl<T> DList<T> {
|
||||||
pure fn new_link(data: T) -> DListLink<T> {
|
static pure fn new_link(data: T) -> DListLink<T> {
|
||||||
Some(DListNode(@{data: move data, mut linked: true,
|
Some(@DListNode { data: data, linked: true, prev: None, next: None })
|
||||||
mut prev: None, mut next: None}))
|
|
||||||
}
|
}
|
||||||
pure fn assert_mine(nobe: DListNode<T>) {
|
pure fn assert_mine(@self, nobe: @DListNode<T>) {
|
||||||
// These asserts could be stronger if we had node-root back-pointers,
|
// These asserts could be stronger if we had node-root back-pointers,
|
||||||
// but those wouldn't allow for O(1) append.
|
// but those wouldn't allow for O(1) append.
|
||||||
if self.size == 0 {
|
if self.size == 0 {
|
||||||
@ -143,15 +139,15 @@ priv impl<T> DList<T> {
|
|||||||
}
|
}
|
||||||
if !nobe.linked { fail ~"That node isn't linked to any dlist." }
|
if !nobe.linked { fail ~"That node isn't linked to any dlist." }
|
||||||
if !((nobe.prev.is_some()
|
if !((nobe.prev.is_some()
|
||||||
|| managed::ptr_eq(*self.hd.expect(~"headless dlist?"),
|
|| managed::ptr_eq(self.hd.expect(~"headless dlist?"),
|
||||||
*nobe)) &&
|
nobe)) &&
|
||||||
(nobe.next.is_some()
|
(nobe.next.is_some()
|
||||||
|| managed::ptr_eq(*self.tl.expect(~"tailless dlist?"),
|
|| managed::ptr_eq(self.tl.expect(~"tailless dlist?"),
|
||||||
*nobe))) {
|
nobe))) {
|
||||||
fail ~"That node isn't on this dlist."
|
fail ~"That node isn't on this dlist."
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fn make_mine(nobe: DListNode<T>) {
|
fn make_mine(nobe: @DListNode<T>) {
|
||||||
if nobe.prev.is_some() || nobe.next.is_some() || nobe.linked {
|
if nobe.prev.is_some() || nobe.next.is_some() || nobe.linked {
|
||||||
fail ~"Cannot insert node that's already on a dlist!"
|
fail ~"Cannot insert node that's already on a dlist!"
|
||||||
}
|
}
|
||||||
@ -171,7 +167,7 @@ priv impl<T> DList<T> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Remove a node from the list.
|
// Remove a node from the list.
|
||||||
fn unlink(nobe: DListNode<T>) {
|
fn unlink(@self, nobe: @DListNode<T>) {
|
||||||
self.assert_mine(nobe);
|
self.assert_mine(nobe);
|
||||||
assert self.size > 0;
|
assert self.size > 0;
|
||||||
self.link(nobe.prev, nobe.next);
|
self.link(nobe.prev, nobe.next);
|
||||||
@ -181,24 +177,24 @@ priv impl<T> DList<T> {
|
|||||||
self.size -= 1;
|
self.size -= 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn add_head(nobe: DListLink<T>) {
|
fn add_head(@self, nobe: DListLink<T>) {
|
||||||
self.link(nobe, self.hd); // Might set tail too.
|
self.link(nobe, self.hd); // Might set tail too.
|
||||||
self.hd = nobe;
|
self.hd = nobe;
|
||||||
self.size += 1;
|
self.size += 1;
|
||||||
}
|
}
|
||||||
fn add_tail(nobe: DListLink<T>) {
|
fn add_tail(@self, nobe: DListLink<T>) {
|
||||||
self.link(self.tl, nobe); // Might set head too.
|
self.link(self.tl, nobe); // Might set head too.
|
||||||
self.tl = nobe;
|
self.tl = nobe;
|
||||||
self.size += 1;
|
self.size += 1;
|
||||||
}
|
}
|
||||||
fn insert_left(nobe: DListLink<T>, neighbour: DListNode<T>) {
|
fn insert_left(@self, nobe: DListLink<T>, neighbour: @DListNode<T>) {
|
||||||
self.assert_mine(neighbour);
|
self.assert_mine(neighbour);
|
||||||
assert self.size > 0;
|
assert self.size > 0;
|
||||||
self.link(neighbour.prev, nobe);
|
self.link(neighbour.prev, nobe);
|
||||||
self.link(nobe, Some(neighbour));
|
self.link(nobe, Some(neighbour));
|
||||||
self.size += 1;
|
self.size += 1;
|
||||||
}
|
}
|
||||||
fn insert_right(neighbour: DListNode<T>, nobe: DListLink<T>) {
|
fn insert_right(@self, neighbour: @DListNode<T>, nobe: DListLink<T>) {
|
||||||
self.assert_mine(neighbour);
|
self.assert_mine(neighbour);
|
||||||
assert self.size > 0;
|
assert self.size > 0;
|
||||||
self.link(nobe, neighbour.next);
|
self.link(nobe, neighbour.next);
|
||||||
@ -209,50 +205,50 @@ priv impl<T> DList<T> {
|
|||||||
|
|
||||||
impl<T> DList<T> {
|
impl<T> DList<T> {
|
||||||
/// Get the size of the list. O(1).
|
/// Get the size of the list. O(1).
|
||||||
pure fn len() -> uint { self.size }
|
pure fn len(@self) -> uint { self.size }
|
||||||
/// Returns true if the list is empty. O(1).
|
/// Returns true if the list is empty. O(1).
|
||||||
pure fn is_empty() -> bool { self.len() == 0 }
|
pure fn is_empty(@self) -> bool { self.len() == 0 }
|
||||||
/// Returns true if the list is not empty. O(1).
|
/// Returns true if the list is not empty. O(1).
|
||||||
pure fn is_not_empty() -> bool { self.len() != 0 }
|
pure fn is_not_empty(@self) -> bool { self.len() != 0 }
|
||||||
|
|
||||||
/// Add data to the head of the list. O(1).
|
/// Add data to the head of the list. O(1).
|
||||||
fn push_head(data: T) {
|
fn push_head(@self, data: T) {
|
||||||
self.add_head(self.new_link(move data));
|
self.add_head(DList::new_link(data));
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* Add data to the head of the list, and get the new containing
|
* Add data to the head of the list, and get the new containing
|
||||||
* node. O(1).
|
* node. O(1).
|
||||||
*/
|
*/
|
||||||
fn push_head_n(data: T) -> DListNode<T> {
|
fn push_head_n(@self, data: T) -> @DListNode<T> {
|
||||||
let mut nobe = self.new_link(move data);
|
let mut nobe = DList::new_link(data);
|
||||||
self.add_head(nobe);
|
self.add_head(nobe);
|
||||||
option::get(nobe)
|
nobe.get()
|
||||||
}
|
}
|
||||||
/// Add data to the tail of the list. O(1).
|
/// Add data to the tail of the list. O(1).
|
||||||
fn push(data: T) {
|
fn push(@self, data: T) {
|
||||||
self.add_tail(self.new_link(move data));
|
self.add_tail(DList::new_link(data));
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* Add data to the tail of the list, and get the new containing
|
* Add data to the tail of the list, and get the new containing
|
||||||
* node. O(1).
|
* node. O(1).
|
||||||
*/
|
*/
|
||||||
fn push_n(data: T) -> DListNode<T> {
|
fn push_n(@self, data: T) -> @DListNode<T> {
|
||||||
let mut nobe = self.new_link(move data);
|
let mut nobe = DList::new_link(data);
|
||||||
self.add_tail(nobe);
|
self.add_tail(nobe);
|
||||||
option::get(nobe)
|
nobe.get()
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* Insert data into the middle of the list, left of the given node.
|
* Insert data into the middle of the list, left of the given node.
|
||||||
* O(1).
|
* O(1).
|
||||||
*/
|
*/
|
||||||
fn insert_before(data: T, neighbour: DListNode<T>) {
|
fn insert_before(@self, data: T, neighbour: @DListNode<T>) {
|
||||||
self.insert_left(self.new_link(move data), neighbour);
|
self.insert_left(DList::new_link(data), neighbour);
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* Insert an existing node in the middle of the list, left of the
|
* Insert an existing node in the middle of the list, left of the
|
||||||
* given node. O(1).
|
* given node. O(1).
|
||||||
*/
|
*/
|
||||||
fn insert_n_before(nobe: DListNode<T>, neighbour: DListNode<T>) {
|
fn insert_n_before(@self, nobe: @DListNode<T>, neighbour: @DListNode<T>) {
|
||||||
self.make_mine(nobe);
|
self.make_mine(nobe);
|
||||||
self.insert_left(Some(nobe), neighbour);
|
self.insert_left(Some(nobe), neighbour);
|
||||||
}
|
}
|
||||||
@ -260,23 +256,27 @@ impl<T> DList<T> {
|
|||||||
* Insert data in the middle of the list, left of the given node,
|
* Insert data in the middle of the list, left of the given node,
|
||||||
* and get its containing node. O(1).
|
* and get its containing node. O(1).
|
||||||
*/
|
*/
|
||||||
fn insert_before_n(data: T, neighbour: DListNode<T>) -> DListNode<T> {
|
fn insert_before_n(
|
||||||
let mut nobe = self.new_link(move data);
|
@self,
|
||||||
|
data: T,
|
||||||
|
neighbour: @DListNode<T>
|
||||||
|
) -> @DListNode<T> {
|
||||||
|
let mut nobe = DList::new_link(data);
|
||||||
self.insert_left(nobe, neighbour);
|
self.insert_left(nobe, neighbour);
|
||||||
option::get(nobe)
|
nobe.get()
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* Insert data into the middle of the list, right of the given node.
|
* Insert data into the middle of the list, right of the given node.
|
||||||
* O(1).
|
* O(1).
|
||||||
*/
|
*/
|
||||||
fn insert_after(data: T, neighbour: DListNode<T>) {
|
fn insert_after(@self, data: T, neighbour: @DListNode<T>) {
|
||||||
self.insert_right(neighbour, self.new_link(move data));
|
self.insert_right(neighbour, DList::new_link(data));
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* Insert an existing node in the middle of the list, right of the
|
* Insert an existing node in the middle of the list, right of the
|
||||||
* given node. O(1).
|
* given node. O(1).
|
||||||
*/
|
*/
|
||||||
fn insert_n_after(nobe: DListNode<T>, neighbour: DListNode<T>) {
|
fn insert_n_after(@self, nobe: @DListNode<T>, neighbour: @DListNode<T>) {
|
||||||
self.make_mine(nobe);
|
self.make_mine(nobe);
|
||||||
self.insert_right(neighbour, Some(nobe));
|
self.insert_right(neighbour, Some(nobe));
|
||||||
}
|
}
|
||||||
@ -284,38 +284,42 @@ impl<T> DList<T> {
|
|||||||
* Insert data in the middle of the list, right of the given node,
|
* Insert data in the middle of the list, right of the given node,
|
||||||
* and get its containing node. O(1).
|
* and get its containing node. O(1).
|
||||||
*/
|
*/
|
||||||
fn insert_after_n(data: T, neighbour: DListNode<T>) -> DListNode<T> {
|
fn insert_after_n(
|
||||||
let mut nobe = self.new_link(move data);
|
@self,
|
||||||
|
data: T,
|
||||||
|
neighbour: @DListNode<T>
|
||||||
|
) -> @DListNode<T> {
|
||||||
|
let mut nobe = DList::new_link(data);
|
||||||
self.insert_right(neighbour, nobe);
|
self.insert_right(neighbour, nobe);
|
||||||
option::get(nobe)
|
nobe.get()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Remove a node from the head of the list. O(1).
|
/// Remove a node from the head of the list. O(1).
|
||||||
fn pop_n() -> Option<DListNode<T>> {
|
fn pop_n(@self) -> DListLink<T> {
|
||||||
let hd = self.peek_n();
|
let hd = self.peek_n();
|
||||||
hd.map(|nobe| self.unlink(*nobe));
|
hd.map(|nobe| self.unlink(*nobe));
|
||||||
hd
|
hd
|
||||||
}
|
}
|
||||||
/// Remove a node from the tail of the list. O(1).
|
/// Remove a node from the tail of the list. O(1).
|
||||||
fn pop_tail_n() -> Option<DListNode<T>> {
|
fn pop_tail_n(@self) -> DListLink<T> {
|
||||||
let tl = self.peek_tail_n();
|
let tl = self.peek_tail_n();
|
||||||
tl.map(|nobe| self.unlink(*nobe));
|
tl.map(|nobe| self.unlink(*nobe));
|
||||||
tl
|
tl
|
||||||
}
|
}
|
||||||
/// Get the node at the list's head. O(1).
|
/// Get the node at the list's head. O(1).
|
||||||
pure fn peek_n() -> Option<DListNode<T>> { self.hd }
|
pure fn peek_n(@self) -> DListLink<T> { self.hd }
|
||||||
/// Get the node at the list's tail. O(1).
|
/// Get the node at the list's tail. O(1).
|
||||||
pure fn peek_tail_n() -> Option<DListNode<T>> { self.tl }
|
pure fn peek_tail_n(@self) -> DListLink<T> { self.tl }
|
||||||
|
|
||||||
/// Get the node at the list's head, failing if empty. O(1).
|
/// Get the node at the list's head, failing if empty. O(1).
|
||||||
pure fn head_n() -> DListNode<T> {
|
pure fn head_n(@self) -> @DListNode<T> {
|
||||||
match self.hd {
|
match self.hd {
|
||||||
Some(nobe) => nobe,
|
Some(nobe) => nobe,
|
||||||
None => fail ~"Attempted to get the head of an empty dlist."
|
None => fail ~"Attempted to get the head of an empty dlist."
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/// Get the node at the list's tail, failing if empty. O(1).
|
/// Get the node at the list's tail, failing if empty. O(1).
|
||||||
pure fn tail_n() -> DListNode<T> {
|
pure fn tail_n(@self) -> @DListNode<T> {
|
||||||
match self.tl {
|
match self.tl {
|
||||||
Some(nobe) => nobe,
|
Some(nobe) => nobe,
|
||||||
None => fail ~"Attempted to get the tail of an empty dlist."
|
None => fail ~"Attempted to get the tail of an empty dlist."
|
||||||
@ -323,14 +327,14 @@ impl<T> DList<T> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Remove a node from anywhere in the list. O(1).
|
/// Remove a node from anywhere in the list. O(1).
|
||||||
fn remove(nobe: DListNode<T>) { self.unlink(nobe); }
|
fn remove(@self, nobe: @DListNode<T>) { self.unlink(nobe); }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Empty another list onto the end of this list, joining this list's tail
|
* Empty another list onto the end of this list, joining this list's tail
|
||||||
* to the other list's head. O(1).
|
* to the other list's head. O(1).
|
||||||
*/
|
*/
|
||||||
fn append(them: DList<T>) {
|
fn append(@self, them: @DList<T>) {
|
||||||
if managed::ptr_eq(*self, *them) {
|
if managed::ptr_eq(self, them) {
|
||||||
fail ~"Cannot append a dlist to itself!"
|
fail ~"Cannot append a dlist to itself!"
|
||||||
}
|
}
|
||||||
if them.len() > 0 {
|
if them.len() > 0 {
|
||||||
@ -346,8 +350,8 @@ impl<T> DList<T> {
|
|||||||
* Empty another list onto the start of this list, joining the other
|
* Empty another list onto the start of this list, joining the other
|
||||||
* list's tail to this list's head. O(1).
|
* list's tail to this list's head. O(1).
|
||||||
*/
|
*/
|
||||||
fn prepend(them: DList<T>) {
|
fn prepend(@self, them: @DList<T>) {
|
||||||
if managed::ptr_eq(*self, *them) {
|
if managed::ptr_eq(self, them) {
|
||||||
fail ~"Cannot prepend a dlist to itself!"
|
fail ~"Cannot prepend a dlist to itself!"
|
||||||
}
|
}
|
||||||
if them.len() > 0 {
|
if them.len() > 0 {
|
||||||
@ -361,7 +365,7 @@ impl<T> DList<T> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Reverse the list's elements in place. O(n).
|
/// Reverse the list's elements in place. O(n).
|
||||||
fn reverse() {
|
fn reverse(@self) {
|
||||||
do option::while_some(self.hd) |nobe| {
|
do option::while_some(self.hd) |nobe| {
|
||||||
let next_nobe = nobe.next;
|
let next_nobe = nobe.next;
|
||||||
self.remove(nobe);
|
self.remove(nobe);
|
||||||
@ -375,7 +379,7 @@ impl<T> DList<T> {
|
|||||||
* Remove everything from the list. This is important because the cyclic
|
* Remove everything from the list. This is important because the cyclic
|
||||||
* links won't otherwise be automatically refcounted-collected. O(n).
|
* links won't otherwise be automatically refcounted-collected. O(n).
|
||||||
*/
|
*/
|
||||||
fn clear() {
|
fn clear(@self) {
|
||||||
// Cute as it would be to simply detach the list and proclaim "O(1)!",
|
// Cute as it would be to simply detach the list and proclaim "O(1)!",
|
||||||
// the GC would still be a hidden O(n). Better to be honest about it.
|
// the GC would still be a hidden O(n). Better to be honest about it.
|
||||||
while !self.is_empty() {
|
while !self.is_empty() {
|
||||||
@ -384,7 +388,7 @@ impl<T> DList<T> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Iterate over nodes.
|
/// Iterate over nodes.
|
||||||
pure fn each_node(f: fn(DListNode<T>) -> bool) {
|
pure fn each_node(@self, f: fn(@DListNode<T>) -> bool) {
|
||||||
let mut link = self.peek_n();
|
let mut link = self.peek_n();
|
||||||
while link.is_some() {
|
while link.is_some() {
|
||||||
let nobe = link.get();
|
let nobe = link.get();
|
||||||
@ -394,26 +398,26 @@ impl<T> DList<T> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Check data structure integrity. O(n).
|
/// Check data structure integrity. O(n).
|
||||||
fn assert_consistent() {
|
fn assert_consistent(@self) {
|
||||||
if option::is_none(&self.hd) || option::is_none(&self.tl) {
|
if self.hd.is_none() || self.tl.is_none() {
|
||||||
assert option::is_none(&self.hd) && option::is_none(&self.tl);
|
assert self.hd.is_none() && self.tl.is_none();
|
||||||
}
|
}
|
||||||
// iterate forwards
|
// iterate forwards
|
||||||
let mut count = 0;
|
let mut count = 0;
|
||||||
let mut link = self.peek_n();
|
let mut link = self.peek_n();
|
||||||
let mut rabbit = link;
|
let mut rabbit = link;
|
||||||
while option::is_some(&link) {
|
while link.is_some() {
|
||||||
let nobe = option::get(link);
|
let nobe = link.get();
|
||||||
assert nobe.linked;
|
assert nobe.linked;
|
||||||
// check cycle
|
// check cycle
|
||||||
if option::is_some(&rabbit) {
|
if rabbit.is_some() {
|
||||||
rabbit = option::get(rabbit).next;
|
rabbit = rabbit.get().next;
|
||||||
}
|
}
|
||||||
if option::is_some(&rabbit) {
|
if rabbit.is_some() {
|
||||||
rabbit = option::get(rabbit).next;
|
rabbit = rabbit.get().next;
|
||||||
}
|
}
|
||||||
if option::is_some(&rabbit) {
|
if rabbit.is_some() {
|
||||||
assert !managed::ptr_eq(*option::get(rabbit), *nobe);
|
assert !managed::ptr_eq(rabbit.get(), nobe);
|
||||||
}
|
}
|
||||||
// advance
|
// advance
|
||||||
link = nobe.next_link();
|
link = nobe.next_link();
|
||||||
@ -423,18 +427,18 @@ impl<T> DList<T> {
|
|||||||
// iterate backwards - some of this is probably redundant.
|
// iterate backwards - some of this is probably redundant.
|
||||||
link = self.peek_tail_n();
|
link = self.peek_tail_n();
|
||||||
rabbit = link;
|
rabbit = link;
|
||||||
while option::is_some(&link) {
|
while link.is_some() {
|
||||||
let nobe = option::get(link);
|
let nobe = link.get();
|
||||||
assert nobe.linked;
|
assert nobe.linked;
|
||||||
// check cycle
|
// check cycle
|
||||||
if option::is_some(&rabbit) {
|
if rabbit.is_some() {
|
||||||
rabbit = option::get(rabbit).prev;
|
rabbit = rabbit.get().prev;
|
||||||
}
|
}
|
||||||
if option::is_some(&rabbit) {
|
if rabbit.is_some() {
|
||||||
rabbit = option::get(rabbit).prev;
|
rabbit = rabbit.get().prev;
|
||||||
}
|
}
|
||||||
if option::is_some(&rabbit) {
|
if rabbit.is_some() {
|
||||||
assert !managed::ptr_eq(*option::get(rabbit), *nobe);
|
assert !managed::ptr_eq(rabbit.get(), nobe);
|
||||||
}
|
}
|
||||||
// advance
|
// advance
|
||||||
link = nobe.prev_link();
|
link = nobe.prev_link();
|
||||||
@ -446,21 +450,33 @@ impl<T> DList<T> {
|
|||||||
|
|
||||||
impl<T: Copy> DList<T> {
|
impl<T: Copy> DList<T> {
|
||||||
/// Remove data from the head of the list. O(1).
|
/// Remove data from the head of the list. O(1).
|
||||||
fn pop() -> Option<T> { self.pop_n().map (|nobe| nobe.data) }
|
fn pop(@self) -> Option<T> {
|
||||||
|
self.pop_n().map(|nobe| nobe.data)
|
||||||
|
}
|
||||||
|
|
||||||
/// Remove data from the tail of the list. O(1).
|
/// Remove data from the tail of the list. O(1).
|
||||||
fn pop_tail() -> Option<T> { self.pop_tail_n().map (|nobe| nobe.data) }
|
fn pop_tail(@self) -> Option<T> {
|
||||||
|
self.pop_tail_n().map(|nobe| nobe.data)
|
||||||
|
}
|
||||||
|
|
||||||
/// Get data at the list's head. O(1).
|
/// Get data at the list's head. O(1).
|
||||||
pure fn peek() -> Option<T> { self.peek_n().map (|nobe| nobe.data) }
|
pure fn peek(@self) -> Option<T> {
|
||||||
|
self.peek_n().map(|nobe| nobe.data)
|
||||||
|
}
|
||||||
|
|
||||||
/// Get data at the list's tail. O(1).
|
/// Get data at the list's tail. O(1).
|
||||||
pure fn peek_tail() -> Option<T> {
|
pure fn peek_tail(@self) -> Option<T> {
|
||||||
self.peek_tail_n().map (|nobe| nobe.data)
|
self.peek_tail_n().map (|nobe| nobe.data)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get data at the list's head, failing if empty. O(1).
|
/// Get data at the list's head, failing if empty. O(1).
|
||||||
pure fn head() -> T { self.head_n().data }
|
pure fn head(@self) -> T { self.head_n().data }
|
||||||
|
|
||||||
/// Get data at the list's tail, failing if empty. O(1).
|
/// Get data at the list's tail, failing if empty. O(1).
|
||||||
pure fn tail() -> T { self.tail_n().data }
|
pure fn tail(@self) -> T { self.tail_n().data }
|
||||||
|
|
||||||
/// Get the elements of the list as a vector. O(n).
|
/// Get the elements of the list as a vector. O(n).
|
||||||
pure fn to_vec() -> ~[T] {
|
pure fn to_vec(@self) -> ~[T] {
|
||||||
let mut v = vec::with_capacity(self.size);
|
let mut v = vec::with_capacity(self.size);
|
||||||
unsafe {
|
unsafe {
|
||||||
// Take this out of the unchecked when iter's functions are pure
|
// Take this out of the unchecked when iter's functions are pure
|
||||||
|
@ -10,12 +10,13 @@
|
|||||||
|
|
||||||
mod inst {
|
mod inst {
|
||||||
use dlist;
|
use dlist;
|
||||||
|
use dlist::DList;
|
||||||
use managed;
|
use managed;
|
||||||
use option::{Option, Some};
|
use option::{Option, Some};
|
||||||
use option;
|
use option;
|
||||||
|
|
||||||
#[allow(non_camel_case_types)]
|
#[allow(non_camel_case_types)]
|
||||||
pub type IMPL_T<A> = dlist::DList<A>;
|
pub type IMPL_T<A> = @DList<A>;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Iterates through the current contents.
|
* Iterates through the current contents.
|
||||||
@ -36,11 +37,11 @@ mod inst {
|
|||||||
}
|
}
|
||||||
if !nobe.linked ||
|
if !nobe.linked ||
|
||||||
(!((nobe.prev.is_some()
|
(!((nobe.prev.is_some()
|
||||||
|| managed::ptr_eq(*self.hd.expect(~"headless dlist?"),
|
|| managed::ptr_eq(self.hd.expect(~"headless dlist?"),
|
||||||
*nobe))
|
nobe))
|
||||||
&& (nobe.next.is_some()
|
&& (nobe.next.is_some()
|
||||||
|| managed::ptr_eq(*self.tl.expect(~"tailless dlist?"),
|
|| managed::ptr_eq(self.tl.expect(~"tailless dlist?"),
|
||||||
*nobe)))) {
|
nobe)))) {
|
||||||
fail ~"Removing a dlist node during iteration is forbidden!"
|
fail ~"Removing a dlist node during iteration is forbidden!"
|
||||||
}
|
}
|
||||||
link = nobe.next_link();
|
link = nobe.next_link();
|
||||||
|
Loading…
Reference in New Issue
Block a user