首页 > 其他分享 >025 通过链表学Rust之使用栈实现双端队列

025 通过链表学Rust之使用栈实现双端队列

时间:2022-11-07 10:37:25浏览次数:41  
标签:node mut right 双端 self pub 链表 025 fn


介绍

视频地址:https://www.bilibili.com/video/av78062009/
相关源码:https://github.com/anonymousGiga/Rust-link-list

详细内容

本节我们使用栈来实现双端队列。

实现栈

栈的实现基本上和最开始的单链表的实现差不多,如下:

pub struct Stack<T> {
head: Link<T>,
}
type Link<T> = Option<Box<Node<T>>>;

struct Node<T> {
elem: T,
next: Link<T>,
}
impl<T> Stack<T> {
pub fn new() -> Self {
Stack { head: None }
}
fn push_node(&mut self, mut node: Box<Node<T>>) {
node.next = self.head.take();
self.head = Some(node);
}
pub fn push(&mut self, elem: T) {
let node = Box::new(Node {
elem: elem,
next: None,
});
self.push_node(node);
}
fn pop_node(&mut self) -> Option<Box<Node<T>>> {
self.head.take().map(|mut node| {
self.head = node.next.take();
node
})
}
pub fn pop(&mut self) -> Option<T> {
self.pop_node().map(|node| {
node.elem
})
}
pub fn peek(&self) -> Option<&T> {
self.head.as_ref().map(|node| {
&node.elem
})
}
pub fn peek_mut(&mut self) -> Option<&mut T> {
self.head.as_mut().map(|node| {
&mut node.elem
})
}
}

impl<T> Drop for Stack<T> {
fn drop(&mut self) {
let mut link = self.head.take();
while let Some(mut node) = link {
link = node.next.take();
}
}
}

实现双端队列

代码如下:

pub struct List<T> {
left: Stack<T>,
right: Stack<T>,
}

impl<T> List<T> {
pub fn new() -> Self {
List { left: Stack::new(), right: Stack::new() }
}
pub fn push_left(&mut self, elem: T) { self.left.push(elem) }
pub fn push_right(&mut self, elem: T) { self.right.push(elem) }
pub fn pop_left(&mut self) -> Option<T> { self.left.pop() }
pub fn pop_right(&mut self) -> Option<T> { self.right.pop() }
pub fn peek_left(&self) -> Option<&T> { self.left.peek() }
pub fn peek_right(&self) -> Option<&T> { self.right.peek() }
pub fn peek_left_mut(&mut self) -> Option<&mut T> { self.left.peek_mut() }
pub fn peek_right_mut(&mut self) -> Option<&mut T> { self.right.peek_mut() }

pub fn go_left(&mut self) -> bool {
self.left.pop_node().map(|node| {
self.right.push_node(node);
}).is_some()
}

pub fn go_right(&mut self) -> bool {
self.right.pop_node().map(|node| {
self.left.push_node(node);
}).is_some()
}
}

测试及完整代码

如下:

pub struct Stack<T> {
head: Link<T>,
}
type Link<T> = Option<Box<Node<T>>>;

struct Node<T> {
elem: T,
next: Link<T>,
}
impl<T> Stack<T> {
pub fn new() -> Self {
Stack { head: None }
}
fn push_node(&mut self, mut node: Box<Node<T>>) {
node.next = self.head.take();
self.head = Some(node);
}
pub fn push(&mut self, elem: T) {
let node = Box::new(Node {
elem: elem,
next: None,
});
self.push_node(node);
}
fn pop_node(&mut self) -> Option<Box<Node<T>>> {
self.head.take().map(|mut node| {
self.head = node.next.take();
node
})
}
pub fn pop(&mut self) -> Option<T> {
self.pop_node().map(|node| {
node.elem
})
}
pub fn peek(&self) -> Option<&T> {
self.head.as_ref().map(|node| {
&node.elem
})
}
pub fn peek_mut(&mut self) -> Option<&mut T> {
self.head.as_mut().map(|node| {
&mut node.elem
})
}
}

impl<T> Drop for Stack<T> {
fn drop(&mut self) {
let mut link = self.head.take();
while let Some(mut node) = link {
link = node.next.take();
}
}
}

pub struct List<T> {
left: Stack<T>,
right: Stack<T>,
}

impl<T> List<T> {
pub fn new() -> Self {
List { left: Stack::new(), right: Stack::new() }
}
pub fn push_left(&mut self, elem: T) { self.left.push(elem) }
pub fn push_right(&mut self, elem: T) { self.right.push(elem) }
pub fn pop_left(&mut self) -> Option<T> { self.left.pop() }
pub fn pop_right(&mut self) -> Option<T> { self.right.pop() }
pub fn peek_left(&self) -> Option<&T> { self.left.peek() }
pub fn peek_right(&self) -> Option<&T> { self.right.peek() }
pub fn peek_left_mut(&mut self) -> Option<&mut T> { self.left.peek_mut() }
pub fn peek_right_mut(&mut self) -> Option<&mut T> { self.right.peek_mut() }

pub fn go_left(&mut self) -> bool {
self.left.pop_node().map(|node| {
self.right.push_node(node);
}).is_some()
}

pub fn go_right(&mut self) -> bool {
self.right.pop_node().map(|node| {
self.left.push_node(node);
}).is_some()
}
}

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

#[test]
fn walk_aboot() {
let mut list = List::new(); // [_]

list.push_left(0); // [0,_]
list.push_right(1); // [0, _, 1]
assert_eq!(list.peek_left(), Some(&0));
assert_eq!(list.peek_right(), Some(&1));

list.push_left(2); // [0, 2, _, 1]
list.push_left(3); // [0, 2, 3, _, 1]
list.push_right(4); // [0, 2, 3, _, 4, 1]

while list.go_left() {} // [_, 0, 2, 3, 4, 1]

assert_eq!(list.pop_left(), None);
assert_eq!(list.pop_right(), Some(0)); // [_, 2, 3, 4, 1]
assert_eq!(list.pop_right(), Some(2)); // [_, 3, 4, 1]

list.push_left(5); // [5, _, 3, 4, 1]
assert_eq!(list.pop_right(), Some(3)); // [5, _, 4, 1]
assert_eq!(list.pop_left(), Some(5)); // [_, 4, 1]
assert_eq!(list.pop_right(), Some(4)); // [_, 1]
assert_eq!(list.pop_right(), Some(1)); // [_]

assert_eq!(list.pop_right(), None);
assert_eq!(list.pop_left(), None);
}
}


标签:node,mut,right,双端,self,pub,链表,025,fn
From: https://blog.51cto.com/u_15862521/5828073

相关文章

  • 024 通过链表学Rust之非安全方式实现链表2
    介绍视频地址:https://www.bilibili.com/video/av78062009/相关源码:https://github.com/anonymousGiga/Rust-link-list详细内容本节实现剩余的迭代器、Drop等。IntoIter实现......
  • 数组、链表
    1.前缀和数组2.差分数组3.滑动窗口算法4.二分搜索5.双指针技巧汇总6.原地修改数组7.单链表的六大解题套路8.链表操作的递归思维......
  • AGC025B
    寄,这都没看出来(考虑把涂绿色看成同时涂上红色和蓝色,显然这是等效的。这样红色和蓝色就独立了,枚举红色的个数即可。时间复杂度\(\mathcalO(n)\)。Code:#include<bits......
  • 114. 二叉树展开为链表
    给你二叉树的根结点 root ,请你将它展开为一个单链表:展开后的单链表应该同样使用 TreeNode ,其中 right 子指针指向链表中下一个结点,而左子指针始终为 null 。展......
  • rust 基础 —— 创建链表
    使用枚举类usecrate::List::{Cons,Nil};enumList{//Cons:元组结构体,包含链表的一个元素和一个指向下一节点的指针Cons(u32,Box<List>),//Nil:末结......
  • leetcode 160. 相交链表 js 实现
    给你两个单链表的头节点 headA 和 headB ,请你找出并返回两个单链表相交的起始节点。如果两个链表不存在相交节点,返回 null 。图示两个链表在节点 c1 开始相交: ......
  • 算法题--从尾到头打印链表
    5要求时间限制:1秒空间限制:32768K题目描述输入一个链表,从尾到头打印链表每个节点的值解题思路链表必须要从头开始访问,如果需要将打印顺序颠倒,可以利用栈的特性。有时......
  • 双链表实现栈,和队列
    packageclass03;importjava.util.LinkedList;importjava.util.Queue;importjava.util.Stack;/***双链表实现栈,和队列*/publicclassCode03_DoubleEndsQu......
  • 单链表,双链表反转
    packageclass03;importjava.util.ArrayList;importjava.util.Collections;importjava.util.List;/***单链表,双链表反转*/publicclassCode01_ReverseLis......
  • 链表的头插法与尾插
    链表是数据结构的一种,多个节点指向形成一个连接在向链表中添加数据时存在两种插入方法:头插法:每插入一个节点,都会代替原来的头部的节点,然后新的头部节点的指针指向......