2012-12-03 18:48:01 -06:00
|
|
|
// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
|
|
|
|
// file at the top-level directory of this distribution and at
|
|
|
|
// http://rust-lang.org/COPYRIGHT.
|
|
|
|
//
|
|
|
|
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
|
|
|
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
|
|
|
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
|
|
|
// option. This file may not be copied, modified, or distributed
|
|
|
|
// except according to those terms.
|
|
|
|
|
2012-09-19 18:52:32 -05:00
|
|
|
/*!
|
|
|
|
|
|
|
|
A doubly-linked list. Supports O(1) head, tail, count, push, pop, etc.
|
|
|
|
|
|
|
|
# Safety note
|
|
|
|
|
|
|
|
Do not use ==, !=, <, etc on doubly-linked lists -- it may not terminate.
|
|
|
|
|
|
|
|
*/
|
|
|
|
|
2012-08-13 19:11:33 -05:00
|
|
|
// NB: transitionary, de-mode-ing.
|
2012-10-03 16:52:09 -05:00
|
|
|
#[forbid(deprecated_mode)];
|
2012-08-13 19:11:33 -05:00
|
|
|
#[forbid(deprecated_pattern)];
|
|
|
|
|
2013-01-08 21:37:25 -06:00
|
|
|
use kinds::Copy;
|
2012-12-23 16:41:37 -06:00
|
|
|
use managed;
|
2013-01-08 21:37:25 -06:00
|
|
|
use option::{None, Option, Some};
|
2012-12-23 16:41:37 -06:00
|
|
|
use option;
|
|
|
|
use vec;
|
|
|
|
|
2013-01-24 17:40:46 -06:00
|
|
|
pub type DListLink<T> = Option<@DListNode<T>>;
|
2012-06-29 23:21:15 -05:00
|
|
|
|
2013-01-24 17:40:46 -06:00
|
|
|
pub struct DListNode<T> {
|
2012-06-29 23:21:15 -05:00
|
|
|
data: T,
|
2012-07-17 18:03:54 -05:00
|
|
|
mut linked: bool, // for assertions
|
2012-08-14 18:54:13 -05:00
|
|
|
mut prev: DListLink<T>,
|
2013-01-24 17:40:46 -06:00
|
|
|
mut next: DListLink<T>,
|
|
|
|
}
|
|
|
|
|
|
|
|
pub struct DList<T> {
|
|
|
|
mut size: uint,
|
|
|
|
mut hd: DListLink<T>,
|
|
|
|
mut tl: DListLink<T>,
|
2012-08-27 16:22:25 -05:00
|
|
|
}
|
2012-06-29 23:21:15 -05:00
|
|
|
|
2012-08-14 18:54:13 -05:00
|
|
|
priv impl<T> DListNode<T> {
|
2013-01-24 17:40:46 -06:00
|
|
|
pure fn assert_links(@self) {
|
2012-08-06 14:34:08 -05:00
|
|
|
match self.next {
|
2012-08-20 14:23:37 -05:00
|
|
|
Some(neighbour) => match neighbour.prev {
|
2013-01-24 17:40:46 -06:00
|
|
|
Some(me) => if !managed::ptr_eq(self, me) {
|
2012-08-03 21:59:04 -05:00
|
|
|
fail ~"Asymmetric next-link in dlist node."
|
2012-08-06 19:14:32 -05:00
|
|
|
},
|
2012-08-20 14:23:37 -05:00
|
|
|
None => fail ~"One-way next-link in dlist node."
|
2012-08-06 19:14:32 -05:00
|
|
|
},
|
2012-08-20 14:23:37 -05:00
|
|
|
None => ()
|
2012-06-29 23:21:15 -05:00
|
|
|
}
|
2012-08-06 14:34:08 -05:00
|
|
|
match self.prev {
|
2012-08-20 14:23:37 -05:00
|
|
|
Some(neighbour) => match neighbour.next {
|
2013-01-24 17:40:46 -06:00
|
|
|
Some(me) => if !managed::ptr_eq(me, self) {
|
2012-08-03 21:59:04 -05:00
|
|
|
fail ~"Asymmetric prev-link in dlist node."
|
2012-08-06 19:14:32 -05:00
|
|
|
},
|
2012-08-20 14:23:37 -05:00
|
|
|
None => fail ~"One-way prev-link in dlist node."
|
2012-08-06 19:14:32 -05:00
|
|
|
},
|
2012-08-20 14:23:37 -05:00
|
|
|
None => ()
|
2012-06-29 23:21:15 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-08-14 18:54:13 -05:00
|
|
|
impl<T> DListNode<T> {
|
2012-07-04 16:53:12 -05:00
|
|
|
/// Get the next node in the list, if there is one.
|
2013-01-24 17:40:46 -06:00
|
|
|
pure fn next_link(@self) -> DListLink<T> {
|
2012-06-29 23:21:15 -05:00
|
|
|
self.assert_links();
|
|
|
|
self.next
|
|
|
|
}
|
2012-07-04 16:53:12 -05:00
|
|
|
/// Get the next node in the list, failing if there isn't one.
|
2013-01-24 17:40:46 -06:00
|
|
|
pure fn next_node(@self) -> @DListNode<T> {
|
2012-08-06 14:34:08 -05:00
|
|
|
match self.next_link() {
|
2012-08-20 14:23:37 -05:00
|
|
|
Some(nobe) => nobe,
|
|
|
|
None => fail ~"This dlist node has no next neighbour."
|
2012-06-29 23:21:15 -05:00
|
|
|
}
|
|
|
|
}
|
2012-07-04 16:53:12 -05:00
|
|
|
/// Get the previous node in the list, if there is one.
|
2013-01-24 17:40:46 -06:00
|
|
|
pure fn prev_link(@self) -> DListLink<T> {
|
2012-06-29 23:21:15 -05:00
|
|
|
self.assert_links();
|
|
|
|
self.prev
|
|
|
|
}
|
2012-07-04 16:53:12 -05:00
|
|
|
/// Get the previous node in the list, failing if there isn't one.
|
2013-01-24 17:40:46 -06:00
|
|
|
pure fn prev_node(@self) -> @DListNode<T> {
|
2012-08-06 14:34:08 -05:00
|
|
|
match self.prev_link() {
|
2012-08-20 14:23:37 -05:00
|
|
|
Some(nobe) => nobe,
|
|
|
|
None => fail ~"This dlist node has no previous neighbour."
|
2012-06-29 23:21:15 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-07-04 16:53:12 -05:00
|
|
|
/// Creates a new dlist node with the given data.
|
2013-01-24 17:40:46 -06:00
|
|
|
pub pure fn new_dlist_node<T>(data: T) -> @DListNode<T> {
|
|
|
|
@DListNode { data: data, linked: false, prev: None, next: None }
|
2012-06-29 23:21:15 -05:00
|
|
|
}
|
|
|
|
|
2012-07-04 16:53:12 -05:00
|
|
|
/// Creates a new, empty dlist.
|
2013-01-24 17:40:46 -06:00
|
|
|
pub pure fn DList<T>() -> @DList<T> {
|
|
|
|
@DList { size: 0, hd: None, tl: None }
|
2012-06-29 23:21:15 -05:00
|
|
|
}
|
|
|
|
|
2012-07-04 16:53:12 -05:00
|
|
|
/// Creates a new dlist with a single element
|
2013-01-24 17:40:46 -06:00
|
|
|
pub pure fn from_elem<T>(data: T) -> @DList<T> {
|
2012-08-27 16:22:25 -05:00
|
|
|
let list = DList();
|
2013-01-24 17:40:46 -06:00
|
|
|
unsafe { list.push(data); }
|
2012-06-29 23:21:15 -05:00
|
|
|
list
|
|
|
|
}
|
|
|
|
|
2013-01-24 17:40:46 -06:00
|
|
|
pub fn from_vec<T: Copy>(vec: &[T]) -> @DList<T> {
|
2012-08-27 16:22:25 -05:00
|
|
|
do vec::foldl(DList(), vec) |list,data| {
|
2012-09-28 00:20:47 -05:00
|
|
|
list.push(*data); // Iterating left-to-right -- add newly to the tail.
|
2012-06-29 23:21:15 -05:00
|
|
|
list
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-07-17 18:03:54 -05:00
|
|
|
/// Produce a list from a list of lists, leaving no elements behind in the
|
|
|
|
/// input. O(number of sub-lists).
|
2013-01-24 17:40:46 -06:00
|
|
|
pub fn concat<T>(lists: @DList<@DList<T>>) -> @DList<T> {
|
2012-08-27 16:22:25 -05:00
|
|
|
let result = DList();
|
2012-07-17 18:03:54 -05:00
|
|
|
while !lists.is_empty() {
|
|
|
|
result.append(lists.pop().get());
|
|
|
|
}
|
|
|
|
result
|
|
|
|
}
|
|
|
|
|
2012-08-14 18:54:13 -05:00
|
|
|
priv impl<T> DList<T> {
|
2013-01-24 17:40:46 -06:00
|
|
|
static pure fn new_link(data: T) -> DListLink<T> {
|
|
|
|
Some(@DListNode { data: data, linked: true, prev: None, next: None })
|
2012-06-29 23:21:15 -05:00
|
|
|
}
|
2013-01-24 17:40:46 -06:00
|
|
|
pure fn assert_mine(@self, nobe: @DListNode<T>) {
|
2012-07-17 18:03:54 -05:00
|
|
|
// These asserts could be stronger if we had node-root back-pointers,
|
|
|
|
// but those wouldn't allow for O(1) append.
|
|
|
|
if self.size == 0 {
|
|
|
|
fail ~"This dlist is empty; that node can't be on it."
|
|
|
|
}
|
|
|
|
if !nobe.linked { fail ~"That node isn't linked to any dlist." }
|
|
|
|
if !((nobe.prev.is_some()
|
2013-01-24 17:40:46 -06:00
|
|
|
|| managed::ptr_eq(self.hd.expect(~"headless dlist?"),
|
|
|
|
nobe)) &&
|
2012-07-17 18:03:54 -05:00
|
|
|
(nobe.next.is_some()
|
2013-01-24 17:40:46 -06:00
|
|
|
|| managed::ptr_eq(self.tl.expect(~"tailless dlist?"),
|
|
|
|
nobe))) {
|
2012-07-17 18:03:54 -05:00
|
|
|
fail ~"That node isn't on this dlist."
|
2012-06-29 23:21:15 -05:00
|
|
|
}
|
|
|
|
}
|
2013-01-24 17:40:46 -06:00
|
|
|
fn make_mine(nobe: @DListNode<T>) {
|
2012-07-17 18:03:54 -05:00
|
|
|
if nobe.prev.is_some() || nobe.next.is_some() || nobe.linked {
|
2012-07-14 00:57:48 -05:00
|
|
|
fail ~"Cannot insert node that's already on a dlist!"
|
2012-06-29 23:21:15 -05:00
|
|
|
}
|
2012-07-17 18:03:54 -05:00
|
|
|
nobe.linked = true;
|
2012-06-29 23:21:15 -05:00
|
|
|
}
|
|
|
|
// Link two nodes together. If either of them are 'none', also sets
|
|
|
|
// the head and/or tail pointers appropriately.
|
|
|
|
#[inline(always)]
|
2012-10-02 13:37:37 -05:00
|
|
|
fn link(before: DListLink<T>, after: DListLink<T>) {
|
2012-08-06 14:34:08 -05:00
|
|
|
match before {
|
2012-08-20 14:23:37 -05:00
|
|
|
Some(neighbour) => neighbour.next = after,
|
|
|
|
None => self.hd = after
|
2012-06-29 23:21:15 -05:00
|
|
|
}
|
2012-08-06 14:34:08 -05:00
|
|
|
match after {
|
2012-08-20 14:23:37 -05:00
|
|
|
Some(neighbour) => neighbour.prev = before,
|
|
|
|
None => self.tl = before
|
2012-06-29 23:21:15 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
// Remove a node from the list.
|
2013-01-24 17:40:46 -06:00
|
|
|
fn unlink(@self, nobe: @DListNode<T>) {
|
2012-06-29 23:21:15 -05:00
|
|
|
self.assert_mine(nobe);
|
|
|
|
assert self.size > 0;
|
2012-09-18 13:46:39 -05:00
|
|
|
self.link(nobe.prev, nobe.next);
|
2012-08-20 14:23:37 -05:00
|
|
|
nobe.prev = None; // Release extraneous references.
|
|
|
|
nobe.next = None;
|
2012-07-17 18:03:54 -05:00
|
|
|
nobe.linked = false;
|
2012-06-29 23:21:15 -05:00
|
|
|
self.size -= 1;
|
|
|
|
}
|
|
|
|
|
2013-01-24 17:40:46 -06:00
|
|
|
fn add_head(@self, nobe: DListLink<T>) {
|
2012-09-18 13:46:39 -05:00
|
|
|
self.link(nobe, self.hd); // Might set tail too.
|
2012-06-29 23:21:15 -05:00
|
|
|
self.hd = nobe;
|
|
|
|
self.size += 1;
|
|
|
|
}
|
2013-01-24 17:40:46 -06:00
|
|
|
fn add_tail(@self, nobe: DListLink<T>) {
|
2012-09-18 13:46:39 -05:00
|
|
|
self.link(self.tl, nobe); // Might set head too.
|
2012-06-29 23:21:15 -05:00
|
|
|
self.tl = nobe;
|
|
|
|
self.size += 1;
|
|
|
|
}
|
2013-01-24 17:40:46 -06:00
|
|
|
fn insert_left(@self, nobe: DListLink<T>, neighbour: @DListNode<T>) {
|
2012-06-29 23:21:15 -05:00
|
|
|
self.assert_mine(neighbour);
|
|
|
|
assert self.size > 0;
|
2012-09-18 13:46:39 -05:00
|
|
|
self.link(neighbour.prev, nobe);
|
|
|
|
self.link(nobe, Some(neighbour));
|
2012-06-29 23:21:15 -05:00
|
|
|
self.size += 1;
|
|
|
|
}
|
2013-01-24 17:40:46 -06:00
|
|
|
fn insert_right(@self, neighbour: @DListNode<T>, nobe: DListLink<T>) {
|
2012-06-29 23:21:15 -05:00
|
|
|
self.assert_mine(neighbour);
|
|
|
|
assert self.size > 0;
|
2012-09-18 13:46:39 -05:00
|
|
|
self.link(nobe, neighbour.next);
|
|
|
|
self.link(Some(neighbour), nobe);
|
2012-06-29 23:21:15 -05:00
|
|
|
self.size += 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-08-14 18:54:13 -05:00
|
|
|
impl<T> DList<T> {
|
2012-07-04 16:53:12 -05:00
|
|
|
/// Get the size of the list. O(1).
|
2013-01-24 17:40:46 -06:00
|
|
|
pure fn len(@self) -> uint { self.size }
|
2012-07-04 16:53:12 -05:00
|
|
|
/// Returns true if the list is empty. O(1).
|
2013-01-24 17:40:46 -06:00
|
|
|
pure fn is_empty(@self) -> bool { self.len() == 0 }
|
2012-06-29 23:21:15 -05:00
|
|
|
|
2012-07-04 16:53:12 -05:00
|
|
|
/// Add data to the head of the list. O(1).
|
2013-01-24 17:40:46 -06:00
|
|
|
fn push_head(@self, data: T) {
|
|
|
|
self.add_head(DList::new_link(data));
|
2012-06-29 23:21:15 -05:00
|
|
|
}
|
2012-07-04 16:53:12 -05:00
|
|
|
/**
|
|
|
|
* Add data to the head of the list, and get the new containing
|
|
|
|
* node. O(1).
|
|
|
|
*/
|
2013-01-24 17:40:46 -06:00
|
|
|
fn push_head_n(@self, data: T) -> @DListNode<T> {
|
|
|
|
let mut nobe = DList::new_link(data);
|
2012-06-29 23:21:15 -05:00
|
|
|
self.add_head(nobe);
|
2013-01-24 17:40:46 -06:00
|
|
|
nobe.get()
|
2012-06-29 23:21:15 -05:00
|
|
|
}
|
2012-07-04 16:53:12 -05:00
|
|
|
/// Add data to the tail of the list. O(1).
|
2013-01-24 17:40:46 -06:00
|
|
|
fn push(@self, data: T) {
|
|
|
|
self.add_tail(DList::new_link(data));
|
2012-06-29 23:21:15 -05:00
|
|
|
}
|
2012-07-04 16:53:12 -05:00
|
|
|
/**
|
|
|
|
* Add data to the tail of the list, and get the new containing
|
|
|
|
* node. O(1).
|
|
|
|
*/
|
2013-01-24 17:40:46 -06:00
|
|
|
fn push_n(@self, data: T) -> @DListNode<T> {
|
|
|
|
let mut nobe = DList::new_link(data);
|
2012-06-29 23:21:15 -05:00
|
|
|
self.add_tail(nobe);
|
2013-01-24 17:40:46 -06:00
|
|
|
nobe.get()
|
2012-06-29 23:21:15 -05:00
|
|
|
}
|
2012-07-04 16:53:12 -05:00
|
|
|
/**
|
|
|
|
* Insert data into the middle of the list, left of the given node.
|
|
|
|
* O(1).
|
|
|
|
*/
|
2013-01-24 17:40:46 -06:00
|
|
|
fn insert_before(@self, data: T, neighbour: @DListNode<T>) {
|
|
|
|
self.insert_left(DList::new_link(data), neighbour);
|
2012-06-29 23:21:15 -05:00
|
|
|
}
|
2012-07-04 16:53:12 -05:00
|
|
|
/**
|
|
|
|
* Insert an existing node in the middle of the list, left of the
|
|
|
|
* given node. O(1).
|
|
|
|
*/
|
2013-01-24 17:40:46 -06:00
|
|
|
fn insert_n_before(@self, nobe: @DListNode<T>, neighbour: @DListNode<T>) {
|
2012-06-29 23:21:15 -05:00
|
|
|
self.make_mine(nobe);
|
2012-08-20 14:23:37 -05:00
|
|
|
self.insert_left(Some(nobe), neighbour);
|
2012-06-29 23:21:15 -05:00
|
|
|
}
|
2012-07-04 16:53:12 -05:00
|
|
|
/**
|
|
|
|
* Insert data in the middle of the list, left of the given node,
|
|
|
|
* and get its containing node. O(1).
|
|
|
|
*/
|
2013-01-24 17:40:46 -06:00
|
|
|
fn insert_before_n(
|
|
|
|
@self,
|
|
|
|
data: T,
|
|
|
|
neighbour: @DListNode<T>
|
|
|
|
) -> @DListNode<T> {
|
|
|
|
let mut nobe = DList::new_link(data);
|
2012-06-29 23:21:15 -05:00
|
|
|
self.insert_left(nobe, neighbour);
|
2013-01-24 17:40:46 -06:00
|
|
|
nobe.get()
|
2012-06-29 23:21:15 -05:00
|
|
|
}
|
2012-07-04 16:53:12 -05:00
|
|
|
/**
|
|
|
|
* Insert data into the middle of the list, right of the given node.
|
|
|
|
* O(1).
|
|
|
|
*/
|
2013-01-24 17:40:46 -06:00
|
|
|
fn insert_after(@self, data: T, neighbour: @DListNode<T>) {
|
|
|
|
self.insert_right(neighbour, DList::new_link(data));
|
2012-06-29 23:21:15 -05:00
|
|
|
}
|
2012-07-04 16:53:12 -05:00
|
|
|
/**
|
|
|
|
* Insert an existing node in the middle of the list, right of the
|
|
|
|
* given node. O(1).
|
|
|
|
*/
|
2013-01-24 17:40:46 -06:00
|
|
|
fn insert_n_after(@self, nobe: @DListNode<T>, neighbour: @DListNode<T>) {
|
2012-06-29 23:21:15 -05:00
|
|
|
self.make_mine(nobe);
|
2012-08-20 14:23:37 -05:00
|
|
|
self.insert_right(neighbour, Some(nobe));
|
2012-06-29 23:21:15 -05:00
|
|
|
}
|
2012-07-04 16:53:12 -05:00
|
|
|
/**
|
|
|
|
* Insert data in the middle of the list, right of the given node,
|
|
|
|
* and get its containing node. O(1).
|
|
|
|
*/
|
2013-01-24 17:40:46 -06:00
|
|
|
fn insert_after_n(
|
|
|
|
@self,
|
|
|
|
data: T,
|
|
|
|
neighbour: @DListNode<T>
|
|
|
|
) -> @DListNode<T> {
|
|
|
|
let mut nobe = DList::new_link(data);
|
2012-06-29 23:21:15 -05:00
|
|
|
self.insert_right(neighbour, nobe);
|
2013-01-24 17:40:46 -06:00
|
|
|
nobe.get()
|
2012-06-29 23:21:15 -05:00
|
|
|
}
|
|
|
|
|
2012-07-04 16:53:12 -05:00
|
|
|
/// Remove a node from the head of the list. O(1).
|
2013-01-24 17:40:46 -06:00
|
|
|
fn pop_n(@self) -> DListLink<T> {
|
2012-06-29 23:21:15 -05:00
|
|
|
let hd = self.peek_n();
|
2012-09-26 18:27:12 -05:00
|
|
|
hd.map(|nobe| self.unlink(*nobe));
|
2012-06-29 23:21:15 -05:00
|
|
|
hd
|
|
|
|
}
|
2012-07-04 16:53:12 -05:00
|
|
|
/// Remove a node from the tail of the list. O(1).
|
2013-01-24 17:40:46 -06:00
|
|
|
fn pop_tail_n(@self) -> DListLink<T> {
|
2012-06-29 23:21:15 -05:00
|
|
|
let tl = self.peek_tail_n();
|
2012-09-26 18:27:12 -05:00
|
|
|
tl.map(|nobe| self.unlink(*nobe));
|
2012-06-29 23:21:15 -05:00
|
|
|
tl
|
|
|
|
}
|
2012-07-04 16:53:12 -05:00
|
|
|
/// Get the node at the list's head. O(1).
|
2013-01-24 17:40:46 -06:00
|
|
|
pure fn peek_n(@self) -> DListLink<T> { self.hd }
|
2012-07-04 16:53:12 -05:00
|
|
|
/// Get the node at the list's tail. O(1).
|
2013-01-24 17:40:46 -06:00
|
|
|
pure fn peek_tail_n(@self) -> DListLink<T> { self.tl }
|
2012-06-29 23:21:15 -05:00
|
|
|
|
2012-07-04 16:53:12 -05:00
|
|
|
/// Get the node at the list's head, failing if empty. O(1).
|
2013-01-24 17:40:46 -06:00
|
|
|
pure fn head_n(@self) -> @DListNode<T> {
|
2012-08-06 14:34:08 -05:00
|
|
|
match self.hd {
|
2012-08-20 14:23:37 -05:00
|
|
|
Some(nobe) => nobe,
|
|
|
|
None => fail ~"Attempted to get the head of an empty dlist."
|
2012-06-29 23:21:15 -05:00
|
|
|
}
|
|
|
|
}
|
2012-07-04 16:53:12 -05:00
|
|
|
/// Get the node at the list's tail, failing if empty. O(1).
|
2013-01-24 17:40:46 -06:00
|
|
|
pure fn tail_n(@self) -> @DListNode<T> {
|
2012-08-06 14:34:08 -05:00
|
|
|
match self.tl {
|
2012-08-20 14:23:37 -05:00
|
|
|
Some(nobe) => nobe,
|
|
|
|
None => fail ~"Attempted to get the tail of an empty dlist."
|
2012-06-29 23:21:15 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-07-04 16:53:12 -05:00
|
|
|
/// Remove a node from anywhere in the list. O(1).
|
2013-01-24 17:40:46 -06:00
|
|
|
fn remove(@self, nobe: @DListNode<T>) { self.unlink(nobe); }
|
2012-06-29 23:21:15 -05:00
|
|
|
|
2012-07-17 18:03:54 -05:00
|
|
|
/**
|
|
|
|
* Empty another list onto the end of this list, joining this list's tail
|
|
|
|
* to the other list's head. O(1).
|
|
|
|
*/
|
2013-01-24 17:40:46 -06:00
|
|
|
fn append(@self, them: @DList<T>) {
|
|
|
|
if managed::ptr_eq(self, them) {
|
2012-07-17 18:03:54 -05:00
|
|
|
fail ~"Cannot append a dlist to itself!"
|
|
|
|
}
|
|
|
|
if them.len() > 0 {
|
2012-09-18 13:46:39 -05:00
|
|
|
self.link(self.tl, them.hd);
|
2012-07-17 18:03:54 -05:00
|
|
|
self.tl = them.tl;
|
|
|
|
self.size += them.size;
|
|
|
|
them.size = 0;
|
2012-08-20 14:23:37 -05:00
|
|
|
them.hd = None;
|
|
|
|
them.tl = None;
|
2012-07-17 18:03:54 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
/**
|
|
|
|
* Empty another list onto the start of this list, joining the other
|
|
|
|
* list's tail to this list's head. O(1).
|
|
|
|
*/
|
2013-01-24 17:40:46 -06:00
|
|
|
fn prepend(@self, them: @DList<T>) {
|
|
|
|
if managed::ptr_eq(self, them) {
|
2012-07-17 18:03:54 -05:00
|
|
|
fail ~"Cannot prepend a dlist to itself!"
|
|
|
|
}
|
|
|
|
if them.len() > 0 {
|
2012-09-18 13:46:39 -05:00
|
|
|
self.link(them.tl, self.hd);
|
2012-07-17 18:03:54 -05:00
|
|
|
self.hd = them.hd;
|
|
|
|
self.size += them.size;
|
|
|
|
them.size = 0;
|
2012-08-20 14:23:37 -05:00
|
|
|
them.hd = None;
|
|
|
|
them.tl = None;
|
2012-07-17 18:03:54 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Reverse the list's elements in place. O(n).
|
2013-01-24 17:40:46 -06:00
|
|
|
fn reverse(@self) {
|
2012-07-25 18:51:12 -05:00
|
|
|
do option::while_some(self.hd) |nobe| {
|
|
|
|
let next_nobe = nobe.next;
|
|
|
|
self.remove(nobe);
|
|
|
|
self.make_mine(nobe);
|
2012-08-20 14:23:37 -05:00
|
|
|
self.add_head(Some(nobe));
|
2012-07-25 18:51:12 -05:00
|
|
|
next_nobe
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Remove everything from the list. This is important because the cyclic
|
|
|
|
* links won't otherwise be automatically refcounted-collected. O(n).
|
|
|
|
*/
|
2013-01-24 17:40:46 -06:00
|
|
|
fn clear(@self) {
|
2012-07-25 18:51:12 -05:00
|
|
|
// 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.
|
2012-07-17 18:03:54 -05:00
|
|
|
while !self.is_empty() {
|
2012-07-25 23:23:42 -05:00
|
|
|
let _ = self.pop_n();
|
2012-07-17 18:03:54 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Iterate over nodes.
|
2013-01-24 17:40:46 -06:00
|
|
|
pure fn each_node(@self, f: fn(@DListNode<T>) -> bool) {
|
2012-09-18 13:46:39 -05:00
|
|
|
let mut link = self.peek_n();
|
|
|
|
while link.is_some() {
|
|
|
|
let nobe = link.get();
|
2012-07-17 18:03:54 -05:00
|
|
|
if !f(nobe) { break; }
|
2012-09-18 13:46:39 -05:00
|
|
|
link = nobe.next_link();
|
2012-07-17 18:03:54 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-07-04 16:53:12 -05:00
|
|
|
/// Check data structure integrity. O(n).
|
2013-01-24 17:40:46 -06:00
|
|
|
fn assert_consistent(@self) {
|
|
|
|
if self.hd.is_none() || self.tl.is_none() {
|
|
|
|
assert self.hd.is_none() && self.tl.is_none();
|
2012-06-29 23:21:15 -05:00
|
|
|
}
|
|
|
|
// iterate forwards
|
|
|
|
let mut count = 0;
|
2012-09-18 13:46:39 -05:00
|
|
|
let mut link = self.peek_n();
|
|
|
|
let mut rabbit = link;
|
2013-01-24 17:40:46 -06:00
|
|
|
while link.is_some() {
|
|
|
|
let nobe = link.get();
|
2012-07-17 18:03:54 -05:00
|
|
|
assert nobe.linked;
|
2012-06-29 23:21:15 -05:00
|
|
|
// check cycle
|
2013-01-24 17:40:46 -06:00
|
|
|
if rabbit.is_some() {
|
|
|
|
rabbit = rabbit.get().next;
|
2012-09-21 21:37:57 -05:00
|
|
|
}
|
2013-01-24 17:40:46 -06:00
|
|
|
if rabbit.is_some() {
|
|
|
|
rabbit = rabbit.get().next;
|
2012-09-21 21:37:57 -05:00
|
|
|
}
|
2013-01-24 17:40:46 -06:00
|
|
|
if rabbit.is_some() {
|
|
|
|
assert !managed::ptr_eq(rabbit.get(), nobe);
|
2012-06-29 23:21:15 -05:00
|
|
|
}
|
|
|
|
// advance
|
2012-09-18 13:46:39 -05:00
|
|
|
link = nobe.next_link();
|
2012-06-29 23:21:15 -05:00
|
|
|
count += 1;
|
|
|
|
}
|
|
|
|
assert count == self.len();
|
|
|
|
// iterate backwards - some of this is probably redundant.
|
2012-09-18 13:46:39 -05:00
|
|
|
link = self.peek_tail_n();
|
|
|
|
rabbit = link;
|
2013-01-24 17:40:46 -06:00
|
|
|
while link.is_some() {
|
|
|
|
let nobe = link.get();
|
2012-07-17 18:03:54 -05:00
|
|
|
assert nobe.linked;
|
2012-06-29 23:21:15 -05:00
|
|
|
// check cycle
|
2013-01-24 17:40:46 -06:00
|
|
|
if rabbit.is_some() {
|
|
|
|
rabbit = rabbit.get().prev;
|
2012-09-21 21:37:57 -05:00
|
|
|
}
|
2013-01-24 17:40:46 -06:00
|
|
|
if rabbit.is_some() {
|
|
|
|
rabbit = rabbit.get().prev;
|
2012-09-21 21:37:57 -05:00
|
|
|
}
|
2013-01-24 17:40:46 -06:00
|
|
|
if rabbit.is_some() {
|
|
|
|
assert !managed::ptr_eq(rabbit.get(), nobe);
|
2012-06-29 23:21:15 -05:00
|
|
|
}
|
|
|
|
// advance
|
2012-09-18 13:46:39 -05:00
|
|
|
link = nobe.prev_link();
|
2012-06-29 23:21:15 -05:00
|
|
|
count -= 1;
|
|
|
|
}
|
|
|
|
assert count == 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-09-07 16:52:28 -05:00
|
|
|
impl<T: Copy> DList<T> {
|
2012-07-25 23:23:42 -05:00
|
|
|
/// Remove data from the head of the list. O(1).
|
2013-01-24 17:40:46 -06:00
|
|
|
fn pop(@self) -> Option<T> {
|
|
|
|
self.pop_n().map(|nobe| nobe.data)
|
|
|
|
}
|
|
|
|
|
2012-07-25 23:23:42 -05:00
|
|
|
/// Remove data from the tail of the list. O(1).
|
2013-01-24 17:40:46 -06:00
|
|
|
fn pop_tail(@self) -> Option<T> {
|
|
|
|
self.pop_tail_n().map(|nobe| nobe.data)
|
|
|
|
}
|
|
|
|
|
2012-07-04 16:53:12 -05:00
|
|
|
/// Get data at the list's head. O(1).
|
2013-01-24 17:40:46 -06:00
|
|
|
pure fn peek(@self) -> Option<T> {
|
|
|
|
self.peek_n().map(|nobe| nobe.data)
|
|
|
|
}
|
|
|
|
|
2012-07-04 16:53:12 -05:00
|
|
|
/// Get data at the list's tail. O(1).
|
2013-01-24 17:40:46 -06:00
|
|
|
pure fn peek_tail(@self) -> Option<T> {
|
2012-07-17 18:03:54 -05:00
|
|
|
self.peek_tail_n().map (|nobe| nobe.data)
|
|
|
|
}
|
2013-01-24 17:40:46 -06:00
|
|
|
|
2012-07-04 16:53:12 -05:00
|
|
|
/// Get data at the list's head, failing if empty. O(1).
|
2013-01-24 17:40:46 -06:00
|
|
|
pure fn head(@self) -> T { self.head_n().data }
|
|
|
|
|
2012-07-04 16:53:12 -05:00
|
|
|
/// Get data at the list's tail, failing if empty. O(1).
|
2013-01-24 17:40:46 -06:00
|
|
|
pure fn tail(@self) -> T { self.tail_n().data }
|
|
|
|
|
2012-07-17 18:03:54 -05:00
|
|
|
/// Get the elements of the list as a vector. O(n).
|
2013-01-24 17:40:46 -06:00
|
|
|
pure fn to_vec(@self) -> ~[T] {
|
2012-09-21 20:43:30 -05:00
|
|
|
let mut v = vec::with_capacity(self.size);
|
2012-09-18 13:17:40 -05:00
|
|
|
unsafe {
|
2012-07-17 18:03:54 -05:00
|
|
|
// Take this out of the unchecked when iter's functions are pure
|
|
|
|
for self.eachi |index,data| {
|
2012-09-21 20:43:30 -05:00
|
|
|
v[index] = *data;
|
2012-07-17 18:03:54 -05:00
|
|
|
}
|
|
|
|
}
|
2012-09-10 14:14:14 -05:00
|
|
|
move v
|
2012-07-17 18:03:54 -05:00
|
|
|
}
|
2012-06-29 23:21:15 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
#[cfg(test)]
|
|
|
|
mod tests {
|
2013-01-08 21:37:25 -06:00
|
|
|
use dlist::{DList, concat, from_vec, new_dlist_node};
|
2012-12-27 19:53:04 -06:00
|
|
|
use iter;
|
2013-01-08 21:37:25 -06:00
|
|
|
use option::{None, Some};
|
2012-12-27 19:53:04 -06:00
|
|
|
use vec;
|
|
|
|
|
2012-07-17 18:03:54 -05:00
|
|
|
#[test]
|
2013-01-29 13:47:18 -06:00
|
|
|
pub fn test_dlist_concat() {
|
2012-07-17 18:03:54 -05:00
|
|
|
let a = from_vec(~[1,2]);
|
|
|
|
let b = from_vec(~[3,4]);
|
|
|
|
let c = from_vec(~[5,6]);
|
|
|
|
let d = from_vec(~[7,8]);
|
|
|
|
let ab = from_vec(~[a,b]);
|
|
|
|
let cd = from_vec(~[c,d]);
|
|
|
|
let abcd = concat(concat(from_vec(~[ab,cd])));
|
|
|
|
abcd.assert_consistent(); assert abcd.len() == 8;
|
|
|
|
abcd.assert_consistent(); assert abcd.pop().get() == 1;
|
|
|
|
abcd.assert_consistent(); assert abcd.pop().get() == 2;
|
|
|
|
abcd.assert_consistent(); assert abcd.pop().get() == 3;
|
|
|
|
abcd.assert_consistent(); assert abcd.pop().get() == 4;
|
|
|
|
abcd.assert_consistent(); assert abcd.pop().get() == 5;
|
|
|
|
abcd.assert_consistent(); assert abcd.pop().get() == 6;
|
|
|
|
abcd.assert_consistent(); assert abcd.pop().get() == 7;
|
|
|
|
abcd.assert_consistent(); assert abcd.pop().get() == 8;
|
|
|
|
abcd.assert_consistent(); assert abcd.is_empty();
|
|
|
|
}
|
|
|
|
#[test]
|
2013-01-29 13:47:18 -06:00
|
|
|
pub fn test_dlist_append() {
|
2012-07-17 18:03:54 -05:00
|
|
|
let a = from_vec(~[1,2,3]);
|
|
|
|
let b = from_vec(~[4,5,6]);
|
|
|
|
a.append(b);
|
|
|
|
assert a.len() == 6;
|
|
|
|
assert b.len() == 0;
|
|
|
|
b.assert_consistent();
|
|
|
|
a.assert_consistent(); assert a.pop().get() == 1;
|
|
|
|
a.assert_consistent(); assert a.pop().get() == 2;
|
|
|
|
a.assert_consistent(); assert a.pop().get() == 3;
|
|
|
|
a.assert_consistent(); assert a.pop().get() == 4;
|
|
|
|
a.assert_consistent(); assert a.pop().get() == 5;
|
|
|
|
a.assert_consistent(); assert a.pop().get() == 6;
|
|
|
|
a.assert_consistent(); assert a.is_empty();
|
|
|
|
}
|
|
|
|
#[test]
|
2013-01-29 13:47:18 -06:00
|
|
|
pub fn test_dlist_append_empty() {
|
2012-07-17 18:03:54 -05:00
|
|
|
let a = from_vec(~[1,2,3]);
|
2012-08-27 16:22:25 -05:00
|
|
|
let b = DList::<int>();
|
2012-07-17 18:03:54 -05:00
|
|
|
a.append(b);
|
|
|
|
assert a.len() == 3;
|
|
|
|
assert b.len() == 0;
|
|
|
|
b.assert_consistent();
|
|
|
|
a.assert_consistent(); assert a.pop().get() == 1;
|
|
|
|
a.assert_consistent(); assert a.pop().get() == 2;
|
|
|
|
a.assert_consistent(); assert a.pop().get() == 3;
|
|
|
|
a.assert_consistent(); assert a.is_empty();
|
|
|
|
}
|
|
|
|
#[test]
|
2013-01-29 13:47:18 -06:00
|
|
|
pub fn test_dlist_append_to_empty() {
|
2012-08-27 16:22:25 -05:00
|
|
|
let a = DList::<int>();
|
2012-07-17 18:03:54 -05:00
|
|
|
let b = from_vec(~[4,5,6]);
|
|
|
|
a.append(b);
|
|
|
|
assert a.len() == 3;
|
|
|
|
assert b.len() == 0;
|
|
|
|
b.assert_consistent();
|
|
|
|
a.assert_consistent(); assert a.pop().get() == 4;
|
|
|
|
a.assert_consistent(); assert a.pop().get() == 5;
|
|
|
|
a.assert_consistent(); assert a.pop().get() == 6;
|
|
|
|
a.assert_consistent(); assert a.is_empty();
|
|
|
|
}
|
|
|
|
#[test]
|
2013-01-29 13:47:18 -06:00
|
|
|
pub fn test_dlist_append_two_empty() {
|
2012-08-27 16:22:25 -05:00
|
|
|
let a = DList::<int>();
|
|
|
|
let b = DList::<int>();
|
2012-07-17 18:03:54 -05:00
|
|
|
a.append(b);
|
|
|
|
assert a.len() == 0;
|
|
|
|
assert b.len() == 0;
|
|
|
|
b.assert_consistent();
|
|
|
|
a.assert_consistent();
|
|
|
|
}
|
|
|
|
#[test]
|
|
|
|
#[ignore(cfg(windows))]
|
|
|
|
#[should_fail]
|
2013-01-29 13:47:18 -06:00
|
|
|
pub fn test_dlist_append_self() {
|
2012-08-27 16:22:25 -05:00
|
|
|
let a = DList::<int>();
|
2012-07-17 18:03:54 -05:00
|
|
|
a.append(a);
|
|
|
|
}
|
|
|
|
#[test]
|
|
|
|
#[ignore(cfg(windows))]
|
|
|
|
#[should_fail]
|
2013-01-29 13:47:18 -06:00
|
|
|
pub fn test_dlist_prepend_self() {
|
2012-08-27 16:22:25 -05:00
|
|
|
let a = DList::<int>();
|
2012-07-17 18:03:54 -05:00
|
|
|
a.prepend(a);
|
|
|
|
}
|
|
|
|
#[test]
|
2013-01-29 13:47:18 -06:00
|
|
|
pub fn test_dlist_prepend() {
|
2012-07-17 18:03:54 -05:00
|
|
|
let a = from_vec(~[1,2,3]);
|
|
|
|
let b = from_vec(~[4,5,6]);
|
|
|
|
b.prepend(a);
|
|
|
|
assert a.len() == 0;
|
|
|
|
assert b.len() == 6;
|
|
|
|
a.assert_consistent();
|
|
|
|
b.assert_consistent(); assert b.pop().get() == 1;
|
|
|
|
b.assert_consistent(); assert b.pop().get() == 2;
|
|
|
|
b.assert_consistent(); assert b.pop().get() == 3;
|
|
|
|
b.assert_consistent(); assert b.pop().get() == 4;
|
|
|
|
b.assert_consistent(); assert b.pop().get() == 5;
|
|
|
|
b.assert_consistent(); assert b.pop().get() == 6;
|
|
|
|
b.assert_consistent(); assert b.is_empty();
|
|
|
|
}
|
|
|
|
#[test]
|
2013-01-29 13:47:18 -06:00
|
|
|
pub fn test_dlist_reverse() {
|
2012-07-17 18:03:54 -05:00
|
|
|
let a = from_vec(~[5,4,3,2,1]);
|
|
|
|
a.reverse();
|
|
|
|
assert a.len() == 5;
|
|
|
|
a.assert_consistent(); assert a.pop().get() == 1;
|
|
|
|
a.assert_consistent(); assert a.pop().get() == 2;
|
|
|
|
a.assert_consistent(); assert a.pop().get() == 3;
|
|
|
|
a.assert_consistent(); assert a.pop().get() == 4;
|
|
|
|
a.assert_consistent(); assert a.pop().get() == 5;
|
|
|
|
a.assert_consistent(); assert a.is_empty();
|
|
|
|
}
|
|
|
|
#[test]
|
2013-01-29 13:47:18 -06:00
|
|
|
pub fn test_dlist_reverse_empty() {
|
2012-08-27 16:22:25 -05:00
|
|
|
let a = DList::<int>();
|
2012-07-17 18:03:54 -05:00
|
|
|
a.reverse();
|
|
|
|
assert a.len() == 0;
|
|
|
|
a.assert_consistent();
|
|
|
|
}
|
|
|
|
#[test]
|
2013-01-29 13:47:18 -06:00
|
|
|
pub fn test_dlist_each_node() {
|
2012-07-17 18:03:54 -05:00
|
|
|
let a = from_vec(~[1,2,4,5]);
|
|
|
|
for a.each_node |nobe| {
|
|
|
|
if nobe.data > 3 {
|
|
|
|
a.insert_before(3, nobe);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
assert a.len() == 6;
|
|
|
|
a.assert_consistent(); assert a.pop().get() == 1;
|
|
|
|
a.assert_consistent(); assert a.pop().get() == 2;
|
|
|
|
a.assert_consistent(); assert a.pop().get() == 3;
|
|
|
|
a.assert_consistent(); assert a.pop().get() == 4;
|
|
|
|
a.assert_consistent(); assert a.pop().get() == 3;
|
|
|
|
a.assert_consistent(); assert a.pop().get() == 5;
|
|
|
|
a.assert_consistent(); assert a.is_empty();
|
|
|
|
}
|
2012-06-29 23:21:15 -05:00
|
|
|
#[test]
|
2013-01-29 13:47:18 -06:00
|
|
|
pub fn test_dlist_clear() {
|
2012-07-25 23:23:42 -05:00
|
|
|
let a = from_vec(~[5,4,3,2,1]);
|
|
|
|
a.clear();
|
|
|
|
assert a.len() == 0;
|
|
|
|
a.assert_consistent();
|
|
|
|
}
|
|
|
|
#[test]
|
2013-01-29 13:47:18 -06:00
|
|
|
pub fn test_dlist_is_empty() {
|
2012-08-27 16:22:25 -05:00
|
|
|
let empty = DList::<int>();
|
2012-06-29 23:21:15 -05:00
|
|
|
let full1 = from_vec(~[1,2,3]);
|
|
|
|
assert empty.is_empty();
|
|
|
|
assert !full1.is_empty();
|
|
|
|
}
|
|
|
|
#[test]
|
2013-01-29 13:47:18 -06:00
|
|
|
pub fn test_dlist_head_tail() {
|
2012-06-29 23:21:15 -05:00
|
|
|
let l = from_vec(~[1,2,3]);
|
|
|
|
assert l.head() == 1;
|
|
|
|
assert l.tail() == 3;
|
|
|
|
assert l.len() == 3;
|
|
|
|
}
|
|
|
|
#[test]
|
2013-01-29 13:47:18 -06:00
|
|
|
pub fn test_dlist_pop() {
|
2012-06-29 23:21:15 -05:00
|
|
|
let l = from_vec(~[1,2,3]);
|
|
|
|
assert l.pop().get() == 1;
|
|
|
|
assert l.tail() == 3;
|
|
|
|
assert l.head() == 2;
|
|
|
|
assert l.pop().get() == 2;
|
|
|
|
assert l.tail() == 3;
|
|
|
|
assert l.head() == 3;
|
|
|
|
assert l.pop().get() == 3;
|
|
|
|
assert l.is_empty();
|
|
|
|
assert l.pop().is_none();
|
|
|
|
}
|
|
|
|
#[test]
|
2013-01-29 13:47:18 -06:00
|
|
|
pub fn test_dlist_pop_tail() {
|
2012-06-29 23:21:15 -05:00
|
|
|
let l = from_vec(~[1,2,3]);
|
|
|
|
assert l.pop_tail().get() == 3;
|
|
|
|
assert l.tail() == 2;
|
|
|
|
assert l.head() == 1;
|
|
|
|
assert l.pop_tail().get() == 2;
|
|
|
|
assert l.tail() == 1;
|
|
|
|
assert l.head() == 1;
|
|
|
|
assert l.pop_tail().get() == 1;
|
|
|
|
assert l.is_empty();
|
|
|
|
assert l.pop_tail().is_none();
|
|
|
|
}
|
|
|
|
#[test]
|
2013-01-29 13:47:18 -06:00
|
|
|
pub fn test_dlist_push() {
|
2012-08-27 16:22:25 -05:00
|
|
|
let l = DList::<int>();
|
2012-06-29 23:21:15 -05:00
|
|
|
l.push(1);
|
|
|
|
assert l.head() == 1;
|
|
|
|
assert l.tail() == 1;
|
|
|
|
l.push(2);
|
|
|
|
assert l.head() == 1;
|
|
|
|
assert l.tail() == 2;
|
|
|
|
l.push(3);
|
|
|
|
assert l.head() == 1;
|
|
|
|
assert l.tail() == 3;
|
|
|
|
assert l.len() == 3;
|
|
|
|
}
|
|
|
|
#[test]
|
2013-01-29 13:47:18 -06:00
|
|
|
pub fn test_dlist_push_head() {
|
2012-08-27 16:22:25 -05:00
|
|
|
let l = DList::<int>();
|
2012-06-29 23:21:15 -05:00
|
|
|
l.push_head(3);
|
|
|
|
assert l.head() == 3;
|
|
|
|
assert l.tail() == 3;
|
|
|
|
l.push_head(2);
|
|
|
|
assert l.head() == 2;
|
|
|
|
assert l.tail() == 3;
|
|
|
|
l.push_head(1);
|
|
|
|
assert l.head() == 1;
|
|
|
|
assert l.tail() == 3;
|
|
|
|
assert l.len() == 3;
|
|
|
|
}
|
|
|
|
#[test]
|
2013-01-29 13:47:18 -06:00
|
|
|
pub fn test_dlist_foldl() {
|
2012-06-29 23:21:15 -05:00
|
|
|
let l = from_vec(vec::from_fn(101, |x|x));
|
2012-09-28 18:37:14 -05:00
|
|
|
assert iter::foldl(&l, 0, |accum,elem| *accum+*elem) == 5050;
|
2012-06-29 23:21:15 -05:00
|
|
|
}
|
|
|
|
#[test]
|
2013-01-29 13:47:18 -06:00
|
|
|
pub fn test_dlist_break_early() {
|
2012-07-13 23:23:02 -05:00
|
|
|
let l = from_vec(~[1,2,3,4,5]);
|
|
|
|
let mut x = 0;
|
|
|
|
for l.each |i| {
|
|
|
|
x += 1;
|
2012-09-19 18:55:01 -05:00
|
|
|
if (*i == 3) { break; }
|
2012-07-13 23:23:02 -05:00
|
|
|
}
|
|
|
|
assert x == 3;
|
|
|
|
}
|
|
|
|
#[test]
|
2013-01-29 13:47:18 -06:00
|
|
|
pub fn test_dlist_remove_head() {
|
2012-08-27 16:22:25 -05:00
|
|
|
let l = DList::<int>();
|
2012-06-29 23:21:15 -05:00
|
|
|
l.assert_consistent(); let one = l.push_n(1);
|
|
|
|
l.assert_consistent(); let _two = l.push_n(2);
|
|
|
|
l.assert_consistent(); let _three = l.push_n(3);
|
|
|
|
l.assert_consistent(); assert l.len() == 3;
|
|
|
|
l.assert_consistent(); l.remove(one);
|
|
|
|
l.assert_consistent(); assert l.len() == 2;
|
|
|
|
l.assert_consistent(); assert l.head() == 2;
|
|
|
|
l.assert_consistent(); assert l.tail() == 3;
|
|
|
|
l.assert_consistent(); assert l.pop().get() == 2;
|
|
|
|
l.assert_consistent(); assert l.pop().get() == 3;
|
|
|
|
l.assert_consistent(); assert l.is_empty();
|
|
|
|
}
|
|
|
|
#[test]
|
2013-01-29 13:47:18 -06:00
|
|
|
pub fn test_dlist_remove_mid() {
|
2012-08-27 16:22:25 -05:00
|
|
|
let l = DList::<int>();
|
2012-06-29 23:21:15 -05:00
|
|
|
l.assert_consistent(); let _one = l.push_n(1);
|
|
|
|
l.assert_consistent(); let two = l.push_n(2);
|
|
|
|
l.assert_consistent(); let _three = l.push_n(3);
|
|
|
|
l.assert_consistent(); assert l.len() == 3;
|
|
|
|
l.assert_consistent(); l.remove(two);
|
|
|
|
l.assert_consistent(); assert l.len() == 2;
|
|
|
|
l.assert_consistent(); assert l.head() == 1;
|
|
|
|
l.assert_consistent(); assert l.tail() == 3;
|
|
|
|
l.assert_consistent(); assert l.pop().get() == 1;
|
|
|
|
l.assert_consistent(); assert l.pop().get() == 3;
|
|
|
|
l.assert_consistent(); assert l.is_empty();
|
|
|
|
}
|
|
|
|
#[test]
|
2013-01-29 13:47:18 -06:00
|
|
|
pub fn test_dlist_remove_tail() {
|
2012-08-27 16:22:25 -05:00
|
|
|
let l = DList::<int>();
|
2012-06-29 23:21:15 -05:00
|
|
|
l.assert_consistent(); let _one = l.push_n(1);
|
|
|
|
l.assert_consistent(); let _two = l.push_n(2);
|
|
|
|
l.assert_consistent(); let three = l.push_n(3);
|
|
|
|
l.assert_consistent(); assert l.len() == 3;
|
|
|
|
l.assert_consistent(); l.remove(three);
|
|
|
|
l.assert_consistent(); assert l.len() == 2;
|
|
|
|
l.assert_consistent(); assert l.head() == 1;
|
|
|
|
l.assert_consistent(); assert l.tail() == 2;
|
|
|
|
l.assert_consistent(); assert l.pop().get() == 1;
|
|
|
|
l.assert_consistent(); assert l.pop().get() == 2;
|
|
|
|
l.assert_consistent(); assert l.is_empty();
|
|
|
|
}
|
|
|
|
#[test]
|
2013-01-29 13:47:18 -06:00
|
|
|
pub fn test_dlist_remove_one_two() {
|
2012-08-27 16:22:25 -05:00
|
|
|
let l = DList::<int>();
|
2012-06-29 23:21:15 -05:00
|
|
|
l.assert_consistent(); let one = l.push_n(1);
|
|
|
|
l.assert_consistent(); let two = l.push_n(2);
|
|
|
|
l.assert_consistent(); let _three = l.push_n(3);
|
|
|
|
l.assert_consistent(); assert l.len() == 3;
|
|
|
|
l.assert_consistent(); l.remove(one);
|
|
|
|
l.assert_consistent(); l.remove(two);
|
|
|
|
// and through and through, the vorpal blade went snicker-snack
|
|
|
|
l.assert_consistent(); assert l.len() == 1;
|
|
|
|
l.assert_consistent(); assert l.head() == 3;
|
|
|
|
l.assert_consistent(); assert l.tail() == 3;
|
|
|
|
l.assert_consistent(); assert l.pop().get() == 3;
|
|
|
|
l.assert_consistent(); assert l.is_empty();
|
|
|
|
}
|
|
|
|
#[test]
|
2013-01-29 13:47:18 -06:00
|
|
|
pub fn test_dlist_remove_one_three() {
|
2012-08-27 16:22:25 -05:00
|
|
|
let l = DList::<int>();
|
2012-06-29 23:21:15 -05:00
|
|
|
l.assert_consistent(); let one = l.push_n(1);
|
|
|
|
l.assert_consistent(); let _two = l.push_n(2);
|
|
|
|
l.assert_consistent(); let three = l.push_n(3);
|
|
|
|
l.assert_consistent(); assert l.len() == 3;
|
|
|
|
l.assert_consistent(); l.remove(one);
|
|
|
|
l.assert_consistent(); l.remove(three);
|
|
|
|
l.assert_consistent(); assert l.len() == 1;
|
|
|
|
l.assert_consistent(); assert l.head() == 2;
|
|
|
|
l.assert_consistent(); assert l.tail() == 2;
|
|
|
|
l.assert_consistent(); assert l.pop().get() == 2;
|
|
|
|
l.assert_consistent(); assert l.is_empty();
|
|
|
|
}
|
|
|
|
#[test]
|
2013-01-29 13:47:18 -06:00
|
|
|
pub fn test_dlist_remove_two_three() {
|
2012-08-27 16:22:25 -05:00
|
|
|
let l = DList::<int>();
|
2012-06-29 23:21:15 -05:00
|
|
|
l.assert_consistent(); let _one = l.push_n(1);
|
|
|
|
l.assert_consistent(); let two = l.push_n(2);
|
|
|
|
l.assert_consistent(); let three = l.push_n(3);
|
|
|
|
l.assert_consistent(); assert l.len() == 3;
|
|
|
|
l.assert_consistent(); l.remove(two);
|
|
|
|
l.assert_consistent(); l.remove(three);
|
|
|
|
l.assert_consistent(); assert l.len() == 1;
|
|
|
|
l.assert_consistent(); assert l.head() == 1;
|
|
|
|
l.assert_consistent(); assert l.tail() == 1;
|
|
|
|
l.assert_consistent(); assert l.pop().get() == 1;
|
|
|
|
l.assert_consistent(); assert l.is_empty();
|
|
|
|
}
|
|
|
|
#[test]
|
2013-01-29 13:47:18 -06:00
|
|
|
pub fn test_dlist_remove_all() {
|
2012-08-27 16:22:25 -05:00
|
|
|
let l = DList::<int>();
|
2012-06-29 23:21:15 -05:00
|
|
|
l.assert_consistent(); let one = l.push_n(1);
|
|
|
|
l.assert_consistent(); let two = l.push_n(2);
|
|
|
|
l.assert_consistent(); let three = l.push_n(3);
|
|
|
|
l.assert_consistent(); assert l.len() == 3;
|
|
|
|
l.assert_consistent(); l.remove(two);
|
|
|
|
l.assert_consistent(); l.remove(three);
|
|
|
|
l.assert_consistent(); l.remove(one); // Twenty-three is number one!
|
2012-08-27 19:49:35 -05:00
|
|
|
l.assert_consistent(); assert l.peek().is_none();
|
2012-06-29 23:21:15 -05:00
|
|
|
l.assert_consistent(); assert l.is_empty();
|
|
|
|
}
|
|
|
|
#[test]
|
2013-01-29 13:47:18 -06:00
|
|
|
pub fn test_dlist_insert_n_before() {
|
2012-08-27 16:22:25 -05:00
|
|
|
let l = DList::<int>();
|
2012-06-29 23:21:15 -05:00
|
|
|
l.assert_consistent(); let _one = l.push_n(1);
|
|
|
|
l.assert_consistent(); let two = l.push_n(2);
|
2012-07-17 18:03:54 -05:00
|
|
|
l.assert_consistent(); let three = new_dlist_node(3);
|
2012-06-29 23:21:15 -05:00
|
|
|
l.assert_consistent(); assert l.len() == 2;
|
|
|
|
l.assert_consistent(); l.insert_n_before(three, two);
|
|
|
|
l.assert_consistent(); assert l.len() == 3;
|
|
|
|
l.assert_consistent(); assert l.head() == 1;
|
|
|
|
l.assert_consistent(); assert l.tail() == 2;
|
|
|
|
l.assert_consistent(); assert l.pop().get() == 1;
|
|
|
|
l.assert_consistent(); assert l.pop().get() == 3;
|
|
|
|
l.assert_consistent(); assert l.pop().get() == 2;
|
|
|
|
l.assert_consistent(); assert l.is_empty();
|
|
|
|
}
|
|
|
|
#[test]
|
2013-01-29 13:47:18 -06:00
|
|
|
pub fn test_dlist_insert_n_after() {
|
2012-08-27 16:22:25 -05:00
|
|
|
let l = DList::<int>();
|
2012-06-29 23:21:15 -05:00
|
|
|
l.assert_consistent(); let one = l.push_n(1);
|
|
|
|
l.assert_consistent(); let _two = l.push_n(2);
|
2012-07-17 18:03:54 -05:00
|
|
|
l.assert_consistent(); let three = new_dlist_node(3);
|
2012-06-29 23:21:15 -05:00
|
|
|
l.assert_consistent(); assert l.len() == 2;
|
|
|
|
l.assert_consistent(); l.insert_n_after(three, one);
|
|
|
|
l.assert_consistent(); assert l.len() == 3;
|
|
|
|
l.assert_consistent(); assert l.head() == 1;
|
|
|
|
l.assert_consistent(); assert l.tail() == 2;
|
|
|
|
l.assert_consistent(); assert l.pop().get() == 1;
|
|
|
|
l.assert_consistent(); assert l.pop().get() == 3;
|
|
|
|
l.assert_consistent(); assert l.pop().get() == 2;
|
|
|
|
l.assert_consistent(); assert l.is_empty();
|
|
|
|
}
|
|
|
|
#[test]
|
2013-01-29 13:47:18 -06:00
|
|
|
pub fn test_dlist_insert_before_head() {
|
2012-08-27 16:22:25 -05:00
|
|
|
let l = DList::<int>();
|
2012-06-29 23:21:15 -05:00
|
|
|
l.assert_consistent(); let one = l.push_n(1);
|
|
|
|
l.assert_consistent(); let _two = l.push_n(2);
|
|
|
|
l.assert_consistent(); assert l.len() == 2;
|
|
|
|
l.assert_consistent(); l.insert_before(3, one);
|
|
|
|
l.assert_consistent(); assert l.len() == 3;
|
|
|
|
l.assert_consistent(); assert l.head() == 3;
|
|
|
|
l.assert_consistent(); assert l.tail() == 2;
|
|
|
|
l.assert_consistent(); assert l.pop().get() == 3;
|
|
|
|
l.assert_consistent(); assert l.pop().get() == 1;
|
|
|
|
l.assert_consistent(); assert l.pop().get() == 2;
|
|
|
|
l.assert_consistent(); assert l.is_empty();
|
|
|
|
}
|
|
|
|
#[test]
|
2013-01-29 13:47:18 -06:00
|
|
|
pub fn test_dlist_insert_after_tail() {
|
2012-08-27 16:22:25 -05:00
|
|
|
let l = DList::<int>();
|
2012-06-29 23:21:15 -05:00
|
|
|
l.assert_consistent(); let _one = l.push_n(1);
|
|
|
|
l.assert_consistent(); let two = l.push_n(2);
|
|
|
|
l.assert_consistent(); assert l.len() == 2;
|
|
|
|
l.assert_consistent(); l.insert_after(3, two);
|
|
|
|
l.assert_consistent(); assert l.len() == 3;
|
|
|
|
l.assert_consistent(); assert l.head() == 1;
|
|
|
|
l.assert_consistent(); assert l.tail() == 3;
|
|
|
|
l.assert_consistent(); assert l.pop().get() == 1;
|
|
|
|
l.assert_consistent(); assert l.pop().get() == 2;
|
|
|
|
l.assert_consistent(); assert l.pop().get() == 3;
|
|
|
|
l.assert_consistent(); assert l.is_empty();
|
|
|
|
}
|
2012-07-02 17:08:09 -05:00
|
|
|
#[test] #[should_fail] #[ignore(cfg(windows))]
|
2013-01-29 13:47:18 -06:00
|
|
|
pub fn test_dlist_asymmetric_link() {
|
2012-08-27 16:22:25 -05:00
|
|
|
let l = DList::<int>();
|
2012-07-05 18:55:01 -05:00
|
|
|
let _one = l.push_n(1);
|
2012-07-02 15:47:55 -05:00
|
|
|
let two = l.push_n(2);
|
2012-08-20 14:23:37 -05:00
|
|
|
two.prev = None;
|
2012-07-02 15:47:55 -05:00
|
|
|
l.assert_consistent();
|
|
|
|
}
|
2012-07-02 17:08:09 -05:00
|
|
|
#[test] #[should_fail] #[ignore(cfg(windows))]
|
2013-01-29 13:47:18 -06:00
|
|
|
pub fn test_dlist_cyclic_list() {
|
2012-08-27 16:22:25 -05:00
|
|
|
let l = DList::<int>();
|
2012-07-02 15:47:55 -05:00
|
|
|
let one = l.push_n(1);
|
|
|
|
let _two = l.push_n(2);
|
|
|
|
let three = l.push_n(3);
|
2012-08-20 14:23:37 -05:00
|
|
|
three.next = Some(one);
|
|
|
|
one.prev = Some(three);
|
2012-07-02 15:47:55 -05:00
|
|
|
l.assert_consistent();
|
|
|
|
}
|
2012-07-02 17:08:09 -05:00
|
|
|
#[test] #[should_fail] #[ignore(cfg(windows))]
|
2013-01-29 13:47:18 -06:00
|
|
|
pub fn test_dlist_headless() {
|
2012-08-27 16:22:25 -05:00
|
|
|
DList::<int>().head();
|
2012-07-02 15:47:55 -05:00
|
|
|
}
|
2012-07-02 17:08:09 -05:00
|
|
|
#[test] #[should_fail] #[ignore(cfg(windows))]
|
2013-01-29 13:47:18 -06:00
|
|
|
pub fn test_dlist_insert_already_present_before() {
|
2012-08-27 16:22:25 -05:00
|
|
|
let l = DList::<int>();
|
2012-07-02 15:47:55 -05:00
|
|
|
let one = l.push_n(1);
|
|
|
|
let two = l.push_n(2);
|
|
|
|
l.insert_n_before(two, one);
|
|
|
|
}
|
2012-07-02 17:08:09 -05:00
|
|
|
#[test] #[should_fail] #[ignore(cfg(windows))]
|
2013-01-29 13:47:18 -06:00
|
|
|
pub fn test_dlist_insert_already_present_after() {
|
2012-08-27 16:22:25 -05:00
|
|
|
let l = DList::<int>();
|
2012-07-02 15:47:55 -05:00
|
|
|
let one = l.push_n(1);
|
|
|
|
let two = l.push_n(2);
|
|
|
|
l.insert_n_after(one, two);
|
|
|
|
}
|
2012-07-02 17:08:09 -05:00
|
|
|
#[test] #[should_fail] #[ignore(cfg(windows))]
|
2013-01-29 13:47:18 -06:00
|
|
|
pub fn test_dlist_insert_before_orphan() {
|
2012-08-27 16:22:25 -05:00
|
|
|
let l = DList::<int>();
|
2012-07-17 18:03:54 -05:00
|
|
|
let one = new_dlist_node(1);
|
|
|
|
let two = new_dlist_node(2);
|
2012-07-02 15:47:55 -05:00
|
|
|
l.insert_n_before(one, two);
|
|
|
|
}
|
2012-07-02 17:08:09 -05:00
|
|
|
#[test] #[should_fail] #[ignore(cfg(windows))]
|
2013-01-29 13:47:18 -06:00
|
|
|
pub fn test_dlist_insert_after_orphan() {
|
2012-08-27 16:22:25 -05:00
|
|
|
let l = DList::<int>();
|
2012-07-17 18:03:54 -05:00
|
|
|
let one = new_dlist_node(1);
|
|
|
|
let two = new_dlist_node(2);
|
2012-07-02 15:47:55 -05:00
|
|
|
l.insert_n_after(two, one);
|
|
|
|
}
|
2012-06-29 23:21:15 -05:00
|
|
|
}
|