Data Structures and Algorithms-Rust Edition Reading Notes-2 Linear Data Structure-Queue

Data Structures and Algorithms-Rust Edition Reading Notes-2 Linear Data Structure-Queue

1. Queue: first in, first out

A queue is an ordered collection of items, where the end where new items are added is called the tail, and the other end where items are removed is called the head. After an element enters the queue from the end of the queue, it will keep moving to the front of the queue until it becomes the next element to be removed.

2. Preliminary knowledge of Rust

1、Some

Rust has two enumeration types set up to handle situations, namely enum Option and enum Result.

There are two types of Option enumerations, namely Some() which represents something and None which represents nothing. If there is a return value, you can use if let, match, unwrap,? Wait for multiple methods to retrieve the value of the Some package according to the situation, if not, it will be None.

There are also two enumeration situations of Result, Ok() indicating correctness and Err() indicating error. The same is true for match, unwrap and other corresponding methods to extract. Extract the content corresponding to the situation respectively.

3. Rust code implementation and running results of queue

queue.rs

/*
 * @Description: 
 * @Author: tianyw
 * @Date: 2023-12-10 17:43:34
 * @LastEditTime: 2023-12-11 21:46:30
 * @LastEditors: tianyw
 */
// 定义队列
#[derive(Debug)] // Debug 是派生宏的名称,此语句为 Queue 结构体实现了 Debug trait

pub struct Queue<T> {
    
     // pub 表示公开的
    cap: usize, // 容量
    data: Vec<T>, // 数据容器
}

impl<T> Queue<T> {
    
     // impl 用于定义类型的实现,如实现 new 方法、is_empty 方法等
    // 初始化空栈
    pub fn new(size: usize) -> Self {
    
     // 指代 Queue 类型
        Self {
    
    
           cap: size,
           data:Vec::with_capacity(size)
        }
    }

    pub fn is_empty(&self) -> bool {
    
    
        0 == Self::len(&self)
    }

    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)
    }

    // 判断是否有剩余空间,如果有的话,就将数据添加到队列中
   pub fn enquue(&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 dequeue(&mut self) -> Option<T> {
    
    
    if self.len() > 0 {
    
    
        self.data.pop()
    }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>(Queue<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 21:54:22
 * @LastEditors: tianyw
 */

mod queue;
fn main() {
    
    
    basic();
    iter();

    fn basic() {
    
    
        let mut q = queue::Queue::new(4);
        let _r1 = q.enquue(1);
        let _r2 = q.enquue(2);
        let _r3 = q.enquue(3);
        let _r4 = q.enquue(4); // 入队

        if let Err(error) = q.enquue(5) {
    
    
            println!("Enqueue error:{error}")
        }

        if let Some(data) = q.dequeue() {
    
     // 出队
            println!("dequeue data: {data}");
        }else {
    
    
            println!("empty queue");
        }

        println!("empty: {}, len: {}", q.is_empty(),q.len());
        println!("full: {}",q.is_full());
        println!("q: {:?}",q);
        q.clear();
        println!("{:?}",q);
    }


    fn iter() {
    
    
        let mut q = queue::Queue::new(4);
        let _r1 = q.enquue(1);
        let _r2 = q.enquue(2);
        let _r3 = q.enquue(3);
        let _r4 = q.enquue(4);

        let sum1 = q.iter().sum::<i32>();
        let mut addend = 0;
        for item in q.iter_mut() {
    
    
            *item += 1;
            addend += 1;
        }
        let sum2 = q.iter().sum::<i32>(); // vec 的 sum 方法
        println!("{sum1} + {addend} = {sum2}");
        println!("sum = {}",q.into_iter().sum::<i32>())
    }
}

cargo run running results

Insert image description here

A typical application of queues is to simulate real-life scenarios in which data is managed in a FIFO manner.

Application: Hot Potato Game

// hot_potato.rs
 
fn hot_potato(names: Vec<&str>, num: usize) -> &str {
    
    
    // 初始化队列,将人名入队
    let mut q = Queue::new(names.len());
    for name in names {
    
     let _nm = q.enqueue(name); }
 
    while q.size() > 1 {
    
    
        // 出入栈中的人名,相当于传递山芋
        for _i in 0..num {
    
    
            let name = q.dequeue().unwrap();
            let _rm = q.enqueue(name);
        }
 
        // 出入栈达到num次,删除一个人名
        let _rm = q.dequeue();
    }
 
    q.dequeue().unwrap()
}
 
fn main() {
    
    
    let name = vec!["Mon","Tom","Kew","Lisa","Marry","Bob"];
    let survivor = hot_potato(name, 8);
    println!("The survival person is {survivor}");
    // 输出“The survival person is Marry”
}

Note that in the above implementation, the count value 8 is greater than the number of names in the queue 6. But this is not a problem, because the queue is like a circle, and when it reaches the end of the queue, it will return to the beginning of the queue until the count value is reached.

Guess you like

Origin blog.csdn.net/yinweimumu/article/details/134937518