双链表 Doubly Linked List

相对于前文提到的单链表, 双链表 doubly linked list (DLL) 中每个节点包含两个指针, 分别指向左右相邻的节点.

其结构如下图所示:

doubly linked list

双链表的优点:

  • 反转双向链表非常容易
  • 它可以在执行过程中轻松分配或重新分配内存
  • 与单链表一样, 它是最容易实现的数据结构
  • 此双向链表的遍历是双向的, 这在单链表中是不可能的
  • 与单链表相比, 删除节点很容易. 单链表删除需要指向要删除的节点和前一个节点的指针, 但在双向链表中, 它只需要要删除的指针. 与其他数据结构 (如数组) 相比, 双向链表的开销较低
  • 可用于实现图算法 graph algorithms

双链表的不足:

  • 与数组和单链表相比, 它使用额外的内存来存储左侧相邻接点
  • 由于内存中的元素是随机存储的, 因此元素是按顺序访问的, 不允许随机访问
  • 遍历双向链表可能比遍历单链表慢
  • 实现和维护双向链表可能比单链表更复杂

双链表的应用场景:

  • 它用于需要前后双向访问的系统
  • 浏览器使用它来实现访问过的网页的前后导航, 即后退和前进按钮
  • 它也用于表示经典的纸牌游戏
  • 各种应用程序也使用它来实现撤消和重做功能
  • 双向链表也用于构建 MRU/LRU (最近使用/最近最少使用) 缓存系统
  • 其他数据结构, 如堆栈, 哈希表, 二叉树也可以使用双向链表构建或编程
  • 在许多操作系统中, 线程调度程序 scheduler (选择哪个进程需要在什么时候运行的东西) 维护当时运行的所有进程的双向链表
  • 实现图算法

链表的节点信息

我们使用单独的链表表头来记录链表的头尾节点信息, 同时还单独记录链表中节点的个数 len.

每个节点包含两个指针分别指向左右相邻节点, 同时在节点上存储元数的值.

其结构大致如下:

#![allow(unused)]

fn main() {
pub struct DoublyLinkedList<T> {
    head: NodePtr<T>,
    tail: NodePtr<T>,
    len: usize,
    _marker: PhantomData<Box<Node<T>>>,
}

type NodePtr<T> = Option<NonNull<Node<T>>>;

struct Node<T> {
    prev: NodePtr<T>,
    next: NodePtr<T>,
    value: T,
}
}

插入节点

批量插入节点

移除节点

访问节点

只有头部节点和尾部节点可以直接访问, 其它节点需要遍历之后才能访问.

#![allow(unused)]
fn main() {
    /// Access the first node.
    #[must_use]
    #[inline]
    pub fn front(&self) -> Option<&T> {
        unsafe { self.head.as_ref().map(|node| &node.as_ref().value) }
    }

    /// Access the first node exclusively.
    #[must_use]
    #[inline]
    pub fn front_mut(&mut self) -> Option<&mut T> {
        unsafe { self.head.as_mut().map(|node| &mut node.as_mut().value) }
    }

    /// Access the last node.
    #[must_use]
    #[inline]
    pub fn back(&self) -> Option<&T> {
        unsafe { self.tail.as_ref().map(|node| &node.as_ref().value) }
    }

    /// Access the last node exclusively.
    #[must_use]
    #[inline]
    pub fn back_mut(&mut self) -> Option<&mut T> {
        unsafe { self.tail.as_mut().map(|node| &mut node.as_mut().value) }
    }
}

迭代器

反转链表

链表分隔

合并链表

算法实现

#![allow(unused)]
fn main() {
use std::cmp::Ordering;
use std::fmt::Formatter;
use std::hash::{Hash, Hasher};
use std::marker::PhantomData;
use std::ptr::NonNull;
use std::{fmt, mem};

pub struct DoublyLinkedList<T> {
    head: NodePtr<T>,
    tail: NodePtr<T>,
    len: usize,
    _marker: PhantomData<Box<Node<T>>>,
}

type NodePtr<T> = Option<NonNull<Node<T>>>;

struct Node<T> {
    prev: NodePtr<T>,
    next: NodePtr<T>,
    value: T,
}

pub struct IntoIter<T>(DoublyLinkedList<T>);

pub struct Iter<'a, T: 'a> {
    head: NodePtr<T>,
    tail: NodePtr<T>,
    len: usize,
    _marker: PhantomData<&'a Node<T>>,
}

pub struct IterMut<'a, T: 'a> {
    head: NodePtr<T>,
    tail: NodePtr<T>,
    len: usize,
    _marker: PhantomData<&'a mut Node<T>>,
}

// Public functions for list.
impl<T> DoublyLinkedList<T> {
    /// Create an empty list.
    #[must_use]
    #[inline]
    pub const fn new() -> Self {
        Self {
            len: 0,
            head: None,
            tail: None,
            _marker: PhantomData,
        }
    }

    // Element access

    /// Access the first node.
    #[must_use]
    #[inline]
    pub fn front(&self) -> Option<&T> {
        unsafe { self.head.as_ref().map(|node| &node.as_ref().value) }
    }

    /// Access the first node exclusively.
    #[must_use]
    #[inline]
    pub fn front_mut(&mut self) -> Option<&mut T> {
        unsafe { self.head.as_mut().map(|node| &mut node.as_mut().value) }
    }

    /// Access the last node.
    #[must_use]
    #[inline]
    pub fn back(&self) -> Option<&T> {
        unsafe { self.tail.as_ref().map(|node| &node.as_ref().value) }
    }

    /// Access the last node exclusively.
    #[must_use]
    #[inline]
    pub fn back_mut(&mut self) -> Option<&mut T> {
        unsafe { self.tail.as_mut().map(|node| &mut node.as_mut().value) }
    }

    pub fn contains(&self, value: &T) -> bool
    where
        T: PartialEq<T>,
    {
        self.iter().any(|item| item == value)
    }

    // Capacity operations

    /// Returns the number of elements in list.
    #[must_use]
    #[inline]
    pub const fn len(&self) -> usize {
        self.len
    }

    /// Check whether the list is empty.
    #[must_use]
    #[inline]
    pub const fn is_empty(&self) -> bool {
        self.len == 0
    }

    // Iterators
    pub fn iter(&self) -> Iter<'_, T> {
        Iter {
            head: self.head,
            tail: self.tail,
            len: self.len,
            _marker: Default::default(),
        }
    }

    pub fn iter_mut(&mut self) -> IterMut<'_, T> {
        IterMut {
            head: self.head,
            tail: self.tail,
            len: self.len,
            _marker: Default::default(),
        }
    }

    // Modifiers

    /// Clear the contents.
    ///
    /// Erases all elements from the list.
    /// After calling this function, size of list is zero.
    pub fn clear(&mut self) {
        let mut other = Self::new();
        mem::swap(self, &mut other);
        drop(other);
    }

    /// Insert element at `pos`.
    ///
    /// # Panics
    ///
    /// Panic if `index > len`.
    pub fn insert_at(&mut self, mut pos: usize, value: T) {
        assert!(pos <= self.len);
        if pos == 0 {
            self.push_front(value);
            return;
        }
        if pos == self.len {
            self.push_back(value);
            return;
        }

        let new_node_ptr = Node::new_ptr(value);
        if let Some(mut node) = self.head {
            while let Some(next_node) = unsafe { node.as_mut().next } {
                if pos == 1 {
                    break;
                }
                pos -= 1;
                node = next_node;
            }

            unsafe { Self::insert_after(node, new_node_ptr); }
            self.len += 1;
        }
    }

    pub fn insert_iter<I: IntoIterator<Item=T>>(&mut self, mut pos: usize, iter: I) {
        assert!(pos <= self.len);
        let mut new_list = DoublyLinkedList::from_iter(iter);

        if pos == 0 {
            self.prepend(&mut new_list);
            return;
        }
        if pos == self.len {
            self.append(&mut new_list);
            return;
        }

        if let Some(mut node) = self.head {
            while let Some(next_node) = unsafe { node.as_mut().next } {
                if pos == 1 {
                    break;
                }
                pos -= 1;
                node = next_node;
            }

            self.len += new_list.len();
            unsafe {
                Self::append_nodes(node, &mut new_list);
            }
        }
    }

    /// Removes the first element equals specific `value`.
    pub fn pop(&mut self, value: &T) -> Option<T>
    where
        T: PartialEq<T>,
    {
        for (index, item) in self.iter().enumerate() {
            if item == value {
                return self.pop_at(index);
            }
        }
        None
    }

    /// Removes the first element satisfying specific condition and returns that element.
    pub fn pop_if<F>(&mut self, f: F) -> Option<T>
    where
        F: Fn(&T) -> bool,
    {
        let mut index: usize = 0;
        for item in self.iter() {
            if f(item) {
                break;
            }
            index += 1;
        }
        self.pop_at(index)
    }

    /// Remove element at `pos` and returns that element.
    ///
    /// # Panics
    ///
    /// Raise panic if `pos >= len`
    pub fn pop_at(&mut self, mut pos: usize) -> Option<T> {
        assert!(pos < self.len);
        if pos == 0 {
            return self.pop_front();
        }
        if pos == self.len - 1 {
            return self.pop_back();
        }
        if let Some(mut node) = self.head {
            while let Some(next_node) = unsafe { node.as_mut().next } {
                if pos == 1 {
                    break;
                }
                pos -= 1;
                node = next_node;
            }

            self.len -= 1;
            unsafe { Self::remove_after(node).map(Node::into_inner) }
        } else {
            None
        }
    }

    /// Add an element to the beginning of list.
    pub fn push_front(&mut self, value: T) {
        let node_ptr = Node::new_ptr(value);
        self.push_front_node(node_ptr);
    }

    /// Remove the first node in the list.
    pub fn pop_front(&mut self) -> Option<T> {
        self.pop_front_node().map(Node::into_inner)
    }

    /// Add an element to the end of list.
    pub fn push_back(&mut self, value: T) {
        let node_ptr = Node::new_ptr(value);
        self.push_back_node(node_ptr);
    }

    /// Remove the last node in the list.
    pub fn pop_back(&mut self) -> Option<T> {
        self.pop_back_node().map(Node::into_inner)
    }

    /// Append all elements in another list to self.
    pub fn append(&mut self, other: &mut Self) {
        match self.tail {
            Some(mut tail) => {
                // connect tail of self to head of other.
                if let Some(mut other_head) = other.head.take() {
                    unsafe {
                        tail.as_mut().next = Some(other_head);
                        other_head.as_mut().prev = Some(tail);
                    }

                    self.tail = other.tail.take();
                    self.len += other.len();
                    other.len = 0;
                }
            }
            None => {
                // self is empty.
                mem::swap(self, other);
            }
        }
    }

    /// Prepend all elements in another list to self.
    #[inline]
    pub fn prepend(&mut self, other: &mut Self) {
        other.append(self);
        self.swap(other);
    }

    /// Change number of elements stored.
    ///
    /// If the current size is greater than `new_size`, extra elements will
    /// be removed.
    /// If current size is less than `new_size`, more elements with default
    /// value are appended.
    pub fn resize(&mut self, new_size: usize)
    where
        T: Default,
    {
        match self.len.cmp(&new_size) {
            Ordering::Equal => (),
            Ordering::Less => {
                for _ in 0..(new_size - self.len) {
                    self.push_back(T::default());
                }
            }
            Ordering::Greater => {
                for _ in 0..(self.len - new_size) {
                    let _node = self.pop_back_node();
                }
            }
        }
    }

    /// Change number of elements stored.
    pub fn resize_with(&mut self, new_size: usize, value: T)
    where
        T: Clone,
    {
        match self.len.cmp(&new_size) {
            Ordering::Equal => (),
            Ordering::Less => {
                for _ in 0..(new_size - self.len) {
                    self.push_back(value.clone());
                }
            }
            Ordering::Greater => {
                for _ in 0..(self.len - new_size) {
                    let _node = self.pop_back_node();
                }
            }
        }
    }

    /// Swap the contents.
    #[inline]
    pub fn swap(&mut self, other: &mut Self) {
        mem::swap(self, other);
    }

    // Operations

    /// Merges two sorted lists.
    pub fn merge(&mut self, _other: &mut Self)
    where
        T: PartialOrd<T>,
    {
        todo!()
    }

    // pub fn merge_by(&mut self, other: &mut Self, predict: P)
    // where
    //     P: PartialOrd<T>,
    // {
    //     todo!()
    // }

    /// Move elements from another list.
    pub fn splice(&mut self, _other: &mut Self) {
        todo!()
    }
    
    /// Reverses the order of the elements.
    pub fn reverse(&mut self) {
        unsafe { Self::base_reverse(self.head) };
        mem::swap(&mut self.head, &mut self.tail);
    }

    /// Removes consecutive duplicate elements.
    ///
    /// Returns number of elements removed.
    pub fn unique(&mut self) -> usize
    where
        T: PartialEq<T>,
    {
        let mut count = 0;
        if let Some(mut node) = self.head {
            while let Some(next_node) = unsafe { node.as_mut().next } {
                unsafe {
                    if node.as_ref().value == next_node.as_ref().value {
                        Self::remove_after(node);
                        count += 1;
                    } else {
                        node = next_node;
                    }
                }
            }
        }

        count
    }

    pub fn sort(&mut self) {
        todo!()
    }

    //pub fn sort_by(&mut self) { }
    //pub fn sort_by_key(&mut self) { }
}

// Private or unsafe functions for list.
impl<T> DoublyLinkedList<T> {
    fn push_front_node(&mut self, node_ptr: NonNull<Node<T>>) {
        unsafe {
            (*node_ptr.as_ptr()).next = self.head;
            (*node_ptr.as_ptr()).prev = None;
        }
        let node = Some(node_ptr);

        match self.head {
            Some(head) => unsafe { (*head.as_ptr()).prev = node },
            None => self.tail = node,
        }

        self.head = node;
        self.len += 1;
    }

    fn push_back_node(&mut self, node_ptr: NonNull<Node<T>>) {
        unsafe {
            (*node_ptr.as_ptr()).next = None;
            (*node_ptr.as_ptr()).prev = self.tail;
        }
        let node = Some(node_ptr);

        match self.tail {
            Some(tail) => unsafe { (*tail.as_ptr()).next = node },
            None => self.head = node,
        }

        self.tail = node;
        self.len += 1;
    }

    fn pop_front_node(&mut self) -> Option<Box<Node<T>>> {
        self.head.map(|old_head| {
            let old_head = unsafe { Node::from_ptr(old_head) };
            self.head = old_head.next;

            match self.head {
                Some(head) => unsafe { (*head.as_ptr()).prev = None },
                None => self.tail = None,
            }

            self.len -= 1;
            old_head
        })
    }

    fn pop_back_node(&mut self) -> Option<Box<Node<T>>> {
        self.tail.map(|old_tail| {
            let old_tail = unsafe { Node::from_ptr(old_tail) };
            self.tail = old_tail.prev;

            match self.tail {
                Some(tail) => unsafe { (*tail.as_ptr()).next = None },
                None => self.head = None,
            }

            self.len -= 1;
            old_tail
        })
    }

    unsafe fn insert_after(mut prev_node: NonNull<Node<T>>, mut new_node_ptr: NonNull<Node<T>>) {
        if let Some(mut next_node) = prev_node.as_mut().next {
            new_node_ptr.as_mut().next = Some(next_node);
            next_node.as_mut().prev = Some(new_node_ptr);
        }
        new_node_ptr.as_mut().prev = Some(prev_node);
        prev_node.as_mut().next = Some(new_node_ptr);
    }

    unsafe fn append_nodes(mut prev_node: NonNull<Node<T>>, other: &mut Self) {
        if other.is_empty() {
            return;
        }

        if let Some(mut next_node) = prev_node.as_mut().next {
            if let Some(mut other_tail) = other.tail.take() {
                other_tail.as_mut().next = Some(next_node);
                next_node.as_mut().prev = Some(other_tail);
            }
        }
        if let Some(mut other_head) = other.head.take() {
            prev_node.as_mut().next = Some(other_head);
            other_head.as_mut().prev = Some(prev_node);
        }

        other.len = 0;
    }

    unsafe fn remove_after(mut node: NonNull<Node<T>>) -> Option<Box<Node<T>>> {
        if let Some(mut next_node) = node.as_mut().next {
            let mut next_next_node = next_node.as_mut().next.take();
            if let Some(next_next_node) = next_next_node.as_mut() {
                next_next_node.as_mut().prev = Some(node);
            }
            node.as_mut().next = next_next_node;

            Some(Node::from_ptr(next_node))
        } else {
            None
        }
    }

    unsafe fn base_reverse(node: NodePtr<T>) {
        let mut temp = node;
        while let Some(mut temp_node) = temp {
            mem::swap(&mut temp_node.as_mut().prev, &mut temp_node.as_mut().next);
            // Old next node is now prev.
            temp = temp_node.as_mut().prev;
        }
    }
}

impl<T> Drop for DoublyLinkedList<T> {
    fn drop(&mut self) {
        while self.pop_front_node().is_some() {
            // dropped
        }
    }
}

impl<T> Default for DoublyLinkedList<T> {
    #[inline]
    fn default() -> Self {
        Self::new()
    }
}

impl<T: fmt::Debug> fmt::Debug for DoublyLinkedList<T> {
    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
        f.debug_list().entries(self).finish()
    }
}

impl<T: Clone> Clone for DoublyLinkedList<T> {
    fn clone(&self) -> Self {
        let mut list = Self::new();
        list.extend(self.iter().cloned());
        list
    }
}

impl<T: PartialEq> PartialEq for DoublyLinkedList<T> {
    fn eq(&self, other: &Self) -> bool {
        self.len == other.len && self.iter().eq(other.iter())
    }
}

impl<T: Eq> Eq for DoublyLinkedList<T> {}

impl<T: Hash> Hash for DoublyLinkedList<T> {
    fn hash<H: Hasher>(&self, state: &mut H) {
        // state.write_length_prefix(self.len);
        state.write_usize(self.len);
        for element in self {
            element.hash(state);
        }
    }
}

impl<T> Extend<T> for DoublyLinkedList<T> {
    fn extend<I: IntoIterator<Item=T>>(&mut self, iter: I) {
        iter.into_iter().for_each(|value| self.push_back(value));
    }
}

impl<T> FromIterator<T> for DoublyLinkedList<T> {
    fn from_iter<I: IntoIterator<Item=T>>(iter: I) -> Self {
        let mut list = Self::new();
        list.extend(iter);
        list
    }
}

impl<T> IntoIterator for DoublyLinkedList<T> {
    type Item = T;
    type IntoIter = IntoIter<T>;

    fn into_iter(self) -> Self::IntoIter {
        IntoIter(self)
    }
}

impl<'a, T> IntoIterator for &'a DoublyLinkedList<T> {
    type Item = &'a T;
    type IntoIter = Iter<'a, T>;

    fn into_iter(self) -> Self::IntoIter {
        self.iter()
    }
}

impl<'a, T> IntoIterator for &'a mut DoublyLinkedList<T> {
    type Item = &'a mut T;
    type IntoIter = IterMut<'a, T>;

    fn into_iter(self) -> Self::IntoIter {
        self.iter_mut()
    }
}

impl<T> Iterator for IntoIter<T> {
    type Item = T;

    #[inline]
    fn next(&mut self) -> Option<T> {
        self.0.pop_front()
    }

    fn size_hint(&self) -> (usize, Option<usize>) {
        (self.0.len, Some(self.0.len))
    }
}

impl<T> DoubleEndedIterator for IntoIter<T> {
    #[inline]
    fn next_back(&mut self) -> Option<Self::Item> {
        self.0.pop_back()
    }
}

impl<T> ExactSizeIterator for IntoIter<T> {}

impl<'a, T> Iterator for Iter<'a, T> {
    type Item = &'a T;

    fn next(&mut self) -> Option<Self::Item> {
        if self.len == 0 {
            None
        } else {
            self.head.map(|node| unsafe {
                let node: &Node<T> = node.as_ref();
                self.len -= 1;
                self.head = node.next;
                &node.value
            })
        }
    }

    #[inline]
    fn size_hint(&self) -> (usize, Option<usize>) {
        (self.len, Some(self.len))
    }

    #[inline]
    fn last(mut self) -> Option<Self::Item>
    where
        Self: Sized,
    {
        self.next_back()
    }
}

impl<'a, T> DoubleEndedIterator for Iter<'a, T> {
    fn next_back(&mut self) -> Option<Self::Item> {
        if self.len == 0 {
            None
        } else {
            self.tail.map(|node| unsafe {
                let node: &Node<T> = node.as_ref();
                self.tail = node.prev;
                self.len -= 1;
                &node.value
            })
        }
    }
}

impl<'a, T> ExactSizeIterator for Iter<'a, T> {}

impl<'a, T> Iterator for IterMut<'a, T> {
    type Item = &'a mut T;

    fn next(&mut self) -> Option<Self::Item> {
        if self.len == 0 {
            None
        } else {
            self.head.map(|mut node| unsafe {
                let node: &mut Node<T> = node.as_mut();
                self.len -= 1;
                self.head = node.next;
                &mut node.value
            })
        }
    }

    #[inline]
    fn size_hint(&self) -> (usize, Option<usize>) {
        (self.len, Some(self.len))
    }

    #[inline]
    fn last(mut self) -> Option<Self::Item>
    where
        Self: Sized,
    {
        self.next_back()
    }
}

impl<'a, T> DoubleEndedIterator for IterMut<'a, T> {
    fn next_back(&mut self) -> Option<Self::Item> {
        if self.len == 0 {
            None
        } else {
            self.tail.map(|mut node| unsafe {
                let node: &mut Node<T> = node.as_mut();
                self.tail = node.prev;
                self.len -= 1;
                &mut node.value
            })
        }
    }
}

impl<'a, T> ExactSizeIterator for IterMut<'a, T> {}

impl<T> Node<T> {
    #[must_use]
    #[inline]
    const fn new(value: T) -> Self {
        Self {
            prev: None,
            next: None,
            value,
        }
    }

    #[must_use]
    #[inline]
    fn new_ptr(value: T) -> NonNull<Self> {
        let node = Box::new(Self::new(value));
        NonNull::from(Box::leak(node))
    }

    #[must_use]
    #[inline]
    unsafe fn from_ptr(ptr: NonNull<Self>) -> Box<Self> {
        Box::from_raw(ptr.as_ptr())
    }

    #[must_use]
    #[inline]
    #[allow(clippy::boxed_local)]
    fn into_inner(self: Box<Self>) -> T {
        self.value
    }
}

#[cfg(test)]
mod tests {
    use super::DoublyLinkedList;

    #[test]
    fn test_is_empty() {
        let list = DoublyLinkedList::<i32>::new();
        assert!(list.is_empty());
    }

    #[test]
    fn test_push() {
        let mut list = DoublyLinkedList::new();
        list.push_front(2);
        list.push_front(3);
        list.push_front(5);
        list.push_front(7);
        list.push_front(11);
        assert_eq!(list.len(), 5);
    }

    #[test]
    fn test_pop_front() {
        let mut list = DoublyLinkedList::new();
        list.push_front(3);
        list.push_front(5);
        list.push_front(7);
        assert_eq!(list.pop_front(), Some(7));
        assert_eq!(list.len(), 2);
        assert_eq!(list.pop_front(), Some(5));
        assert_eq!(list.pop_front(), Some(3));
        assert!(list.is_empty());
    }

    #[test]
    fn test_pop_back() {
        let mut list = DoublyLinkedList::new();
        list.push_back(3);
        list.push_back(5);
        list.push_back(7);
        assert_eq!(list.pop_back(), Some(7));
        assert_eq!(list.len(), 2);
        assert_eq!(list.pop_back(), Some(5));
        assert_eq!(list.pop_back(), Some(3));
        assert!(list.is_empty());
    }

    #[test]
    fn test_back() {
        let mut list = DoublyLinkedList::new();
        list.push_back(5);
        list.push_back(7);
        assert_eq!(list.back(), Some(&7));
        assert_eq!(list.front(), Some(&5));
    }

    #[test]
    fn test_back_mut() {
        let mut list = DoublyLinkedList::new();
        list.push_back(5);
        list.push_back(7);
        if let Some(value) = list.back_mut() {
            *value = 11;
        }
        assert_eq!(list.back(), Some(&11));
    }

    #[test]
    fn test_drop() {
        let mut list = DoublyLinkedList::new();
        for i in 0..(128 * 200) {
            list.push_front(i);
        }
        drop(list);
    }

    #[test]
    fn test_into_iter() {
        let mut list = DoublyLinkedList::new();
        list.push_front(2);
        list.push_front(3);
        list.push_front(5);
        list.push_front(7);
        let mut iter = list.into_iter();
        assert_eq!(iter.next(), Some(7));
        assert_eq!(iter.next(), Some(5));
        assert_eq!(iter.next(), Some(3));
        assert_eq!(iter.next(), Some(2));
        assert_eq!(iter.next(), None);
    }

    #[test]
    fn test_append() {
        let numbers = [1, 2, 3];
        let mut list1 = DoublyLinkedList::new();
        let mut list2 = DoublyLinkedList::from_iter(numbers);
        assert_eq!(list2.len(), numbers.len());
        list1.append(&mut list2);
        assert_eq!(list1.len(), numbers.len());
        assert!(list2.is_empty());
    }

    #[test]
    fn test_prepend() {
        let numbers = [1, 2, 3];
        let mut list1 = DoublyLinkedList::new();
        list1.push_back(4);
        let mut list2 = DoublyLinkedList::from_iter(numbers);
        assert_eq!(list2.len(), numbers.len());
        list1.prepend(&mut list2);
        assert!(list2.is_empty());
        assert_eq!(list1.len(), numbers.len() + 1);
        assert_eq!(list1, DoublyLinkedList::from_iter([1, 2, 3, 4]));
    }

    #[test]
    fn test_extend() {
        let mut list = DoublyLinkedList::new();
        let numbers = [1, 2, 3];
        list.extend(numbers);
        assert_eq!(list, DoublyLinkedList::from_iter(numbers));
    }

    #[test]
    fn test_insert() {
        let mut list = DoublyLinkedList::new();
        list.insert_at(0, 1);
        list.insert_at(0, 0);
        list.insert_at(2, 3);
        list.insert_at(2, 2);
        assert_eq!(list.into_iter().collect::<Vec<_>>(), [0, 1, 2, 3]);
    }

    #[test]
    fn test_insert_range() {
        let mut list = DoublyLinkedList::new();
        list.push_back(0);
        list.push_back(3);
        list.insert_iter(1, [1, 2]);
        assert_eq!(list, DoublyLinkedList::from_iter([0, 1, 2, 3]));
    }

    #[test]
    fn test_contains() {
        let list = DoublyLinkedList::from_iter([1, 2, 3, 4, 5]);
        assert!(list.contains(&3));
        assert!(list.contains(&4));
        assert!(!list.contains(&6));
        assert!(!list.contains(&0));
    }

    #[test]
    fn test_pop() {
        let mut list = DoublyLinkedList::from_iter([1, 2, 3, 4]);
        list.pop(&2);
        assert_eq!(list.len(), 3);
    }

    #[test]
    fn test_pop_at() {
        let mut list = DoublyLinkedList::from_iter([1, 2, 3, 4]);
        let ret = list.pop_at(1);
        assert_eq!(ret, Some(2));
        assert_eq!(list.len(), 3);
    }

    #[test]
    fn test_pop_if() {
        let mut list = DoublyLinkedList::from_iter([1, 2, 3, 4]);
        let ret = list.pop_if(|value| value % 2 == 0);
        assert_eq!(ret, Some(2));
        assert_eq!(list.len(), 3);
        let ret = list.pop_if(|value| value % 2 == 0);
        assert_eq!(ret, Some(4));
        assert_eq!(list.len(), 2);
    }

    #[test]
    fn test_unique() {
        let mut list = DoublyLinkedList::from_iter([1, 1, 2, 2, 3, 1, 1, 2]);
        let expected = [1, 2, 3, 1, 2];
        let ret = list.unique();
        assert_eq!(ret, 3);
        assert_eq!(list.into_iter().collect::<Vec<_>>(), expected);
    }

    #[test]
    fn test_reverse() {
        let mut list = DoublyLinkedList::from_iter([1, 2, 3, 4]);
        assert_eq!(list.iter().copied().collect::<Vec<_>>(), [1, 2, 3, 4]);
        list.reverse();
        assert_eq!(list.into_iter().collect::<Vec<_>>(), [4, 3, 2, 1]);
    }
}
}