数据结构与算法-Rust 版读书笔记-2线性数据结构-双端队列
1、双端队列
deque又称为双端队列,双端队列是与队列类似的项的有序集合。deque有两个端部:首端和尾端。deque不同于队列的地方就在于项的添加和删除是不受限制的,既可以从首尾两端添加项,也可以从首尾两端移除项。在某种意义上,这种混合线性结构提供了栈和队列的所有功能。
虽然deque拥有栈和队列的许多特性,但其不需要像它们一样强制地进行LIFO和FIFO排序,这取决于如何添加和删除数据。deque既可以当作栈使用,也可以当作队列使用,但最好不要如此,因为不同的数据结构都有自身的特性,它们均是为了不同的计算目的而设计的。
2、双端队列的 Rust 代码实现、运行结果
queue.rs
/*
* @Description:
* @Author: tianyw
* @Date: 2023-12-10 17:43:34
* @LastEditTime: 2023-12-11 22:19:06
* @LastEditors: tianyw
*/
// 定义队列
#[derive(Debug)]
pub struct Deque<T> { // pub 表示公开的
cap: usize, // 容量
data: Vec<T>, // 数据容器
}
impl<T> Deque<T> { // impl 用于定义类型的实现,如实现 new 方法、is_empty 方法等
// 初始化空栈
pub fn new(cap: usize) -> Self {
Self {
cap: cap,
data:Vec::with_capacity(cap)
}
}
pub fn is_empty(&self) -> bool {
0 == self.len()
}
pub fn is_full(&self) -> bool {
self.len() == self.cap
}
pub fn len(&self) -> usize { // &self 只可读
self.data.len()
}
// 清空
pub fn clear(&mut self) { // &mut self 可读、可写
self.data = Vec::with_capacity(self.cap)
}
// Vec 的末尾为队首
pub fn add_front(&mut self, val: T) -> Result<(), String> {
if self.len() == self.cap {
return Err("No space available".to_string());
}
self.data.push(val);
Ok(())
}
// Vec 的首部为队尾
pub fn add_rear(&mut self,val: T) -> Result<(), String> {
if self.len() == self.cap {
return Err("No space available".to_string());
}
self.data.insert(0,val);
Ok(())
}
// 从队首移除数据
pub fn remove_front(&mut self) -> Option<T> {
if self.len() > 0 {
self.data.pop()
}else {
None
}
}
// 从队尾移除数据
pub fn remove_rear(&mut self) -> Option<T> {
if self.len() > 0 {
Some(self.data.remove(0))
}else {
None
}
}
// 以下是为双端队列实现的迭代功能
// into_iter:双端队列改变,成为迭代器
// iter: 双端队列不变,得到不可变迭代器
// iter_mut: 双端队列不变,得到可变迭代器
pub fn into_iter(self) -> IntoIter<T> {
IntoIter(self)
}
pub fn iter(&self) -> Iter<T> {
let mut iterator = Iter { stack: Vec::new() };
for item in self.data.iter() {
iterator.stack.push(item);
}
iterator
}
pub fn iter_mut(&mut self) -> IterMut<T> {
let mut iterator = IterMut { stack: Vec::new() };
for item in self.data.iter_mut() {
iterator.stack.push(item);
}
iterator
}
}
// 实现三种迭代功能
pub struct IntoIter<T>(Deque<T>);
impl<T:Clone> Iterator for IntoIter<T> {
type Item = T;
fn next(&mut self) -> Option<Self::Item> {
// 元组的第一个元素不为空
if !self.0.is_empty() {
Some(self.0.data.remove(0))
} else {
None
}
}
}
pub struct Iter<'a,T:'a> { stack: Vec<&'a T>, }
impl<'a,T> Iterator for Iter<'a,T> {
type Item = &'a T;
fn next(&mut self) -> Option<Self::Item> {
if 0 != self.stack.len() {
Some(self.stack.remove(0)) // 索引移除
}else {
None
}
}
}
pub struct IterMut<'a,T:'a> { stack: Vec<&'a mut T> }
impl<'a,T> Iterator for IterMut<'a,T> {
type Item = &'a mut T;
fn next(&mut self) -> Option<Self::Item> {
if 0 != self.stack.len() {
Some(self.stack.remove(0))
}else {
None
}
}
}
main.rs
/*
* @Description:
* @Author: tianyw
* @Date: 2023-12-11 21:29:04
* @LastEditTime: 2023-12-11 22:21:01
* @LastEditors: tianyw
*/
mod deque;
fn main() {
basic();
iter();
fn basic() {
let mut d = deque::Deque::new(4);
let _r1 = d.add_front(1);
let _r2 = d.add_front(2);
let _r3 = d.add_rear(3);
let _r4 = d.add_rear(4); // 入队
if let Err(error) = d.add_front(5) {
println!("Enqueue error:{error}")
}
println!("{:?}",d);
match d.remove_rear() {
Some(data) => println!("remove rear data {data}"),
None => println!("empty deque"),
}
match d.remove_front() {
Some(data) => println!("remove front data {data}"),
None => println!("empty deque"),
}
println!("empty: {},len: {}",d.is_empty(),d.len());
println!("full: {},{:?}",d.is_full(),d);
d.clear();
println!("{:?}",d);
}
fn iter() {
let mut d = deque::Deque::new(4);
let _r1 = d.add_front(1);
let _r2 = d.add_front(2);
let _r3 = d.add_rear(3);
let _r4 = d.add_rear(4);
let sum1 = d.iter().sum::<i32>();
let mut addend = 0;
for item in d.iter_mut() {
*item += 1;
addend += 1;
}
let sum2 = d.iter().sum::<i32>(); // vec 的 sum 方法
println!("{sum1} + {addend} = {sum2}");
assert_eq!(14,d.into_iter().sum::<i32>());
}
}
cargo run 运行结果
应用:回文检测
// palindrome_checker.rs
fn palindrome_checker(pal: &str) -> bool {
// 数据入队
let mut d = Deque::new(pal.len());
for c in pal.chars() {
let _r = d.add_rear(c);
}
let mut is_pal = true;
while d.size() > 1 && is_pal {
// 出队首尾字符
let head = d.remove_front();
let tail = d.remove_rear();
// 比较首尾字符,若不同,则字符串非回文
if head != tail {
is_pal = false;
}
}
is_pal
}
fn main() {
let pal = "rustsur";
let is_pal = palindrome_checker(pal);
println!("{pal} is palindrome string: {is_pal}");
// 输出“rustsur is palindrome string: true”
let pal = "panda";
let is_pal = palindrome_checker(pal);
println!("{pal} is palindrome string: {is_pal}");
// 输出“panda is palindrome string: false”
}