use crate::data_structure::queue::Queue;
pub struct TwoStacksQueue<T> {
s1: Vec<T>,
s2: Vec<T>,
}
impl<T> TwoStacksQueue<T> {
pub fn new() -> Self {
Self {
s1: Vec::<T>::new(),
s2: Vec::<T>::new(),
}
}
pub fn with_capacity(size: usize) -> Self {
Self {
s1: Vec::<T>::with_capacity(size),
s2: Vec::<T>::with_capacity(size),
}
}
fn rebalance(&mut self) {
while self.s1.len() > 0 {
self.s2.push(self.s1.pop().unwrap());
}
}
}
impl<T> Queue<T> for TwoStacksQueue<T> {
fn push_back(&mut self, item: T) {
self.s1.push(item)
}
fn pop_front(&mut self) -> Option<T> {
if self.s2.is_empty() {
self.rebalance();
}
self.s2.pop()
}
fn front(&self) -> Option<&T> {
if !self.s2.is_empty() {
return self.s2.last();
}
self.s1.first()
}
fn is_empty(&self) -> bool {
self.s1.is_empty() && self.s2.is_empty()
}
}
#[cfg(test)]
mod tests {
use crate::data_structure::queue::two_stacks_queue::TwoStacksQueue;
use crate::data_structure::queue::Queue;
extern crate test;
use test::Bencher;
#[test]
fn test_growable_queue_push_pop() {
let mut queue = TwoStacksQueue::<i32>::new();
for i in 0..33 {
queue.push_back(i);
queue.push_back(i + 1);
queue.push_back(i + 2);
assert_eq!(Some(i), queue.pop_front());
assert_eq!(Some(i + 1), queue.pop_front());
assert_eq!(Some(i + 2), queue.pop_front());
assert_eq!(None, queue.pop_front());
}
}
#[test]
fn test_growable_queue_is_empty() {
let mut queue = TwoStacksQueue::<i32>::new();
assert_eq!(true, queue.is_empty());
queue.push_back(1);
assert_eq!(false, queue.is_empty());
queue.pop_front();
assert_eq!(true, queue.is_empty());
}
#[test]
fn test_growable_queue_front() {
let mut queue = TwoStacksQueue::<i32>::new();
assert_eq!(None, queue.front());
queue.push_back(1);
assert_eq!(1, *queue.front().unwrap());
queue.push_back(2);
assert_eq!(1, *queue.front().unwrap());
queue.pop_front();
assert_eq!(2, *queue.front().unwrap());
queue.pop_front();
assert_eq!(None, queue.front());
}
#[bench]
fn bench_growable_queue_push_pop(b: &mut Bencher) {
b.iter(|| {
let mut queue = TwoStacksQueue::<i32>::with_capacity(20);
for i in 0..10000 {
for _ in 0..10 {
queue.push_back(i);
}
for _ in 0..10 {
queue.pop_front();
}
}
});
}
}