Rust数据结构和算法系列[1]-打印机与队列

最近在B站学习了北京大学的北京大学-数据结构与算法Python版 https://www.bilibili.com/video/BV1TJ411Q7zL

由于同时还在学习rust,所以突然想将其里面的数据结构和算法用rust实现一遍

准备一步步来,这次先实现一个教案中的打印机任务模拟,仿照原版的python代码先依样画葫芦

Rust数据结构和算法系列[1]-打印机与队列_第1张图片

 

//一步步来先用最简单的vec包装一个Queue
pub struct Queue{
    data : Vec,
}
impl Queue{
    pub fn new() -> Queue{
        let mut data : Vec = Vec::new();
        
        let queue = Queue
        {
            data : data,
        };
        queue
    }
    pub fn isEmpty(&self) -> bool{
        self.data.is_empty()
    }
    pub fn enqueue(&mut self,item:T){ //入队列
        self.data.insert(0, item);
    }
    pub fn dequeue(&mut self) -> T{ //出队列
        self.data.pop().unwrap()
    }
    pub fn size_of(&self) -> usize{
        self.data.len()
    }
}
//然后是打印机队列的模拟程序
use crate::queue::Queue;
use rand::Rng; //这里需要在Cargo.toml的[dependencies]引入rand = "0.3.17"
struct Printer{
    pagerate : i32, //打印速率,每分钟能打多少页
    currentTask : Option, //当前任务,这里用Option包装一下
    timeRemaining : i64, //剩余时间(s)
}
impl Printer{
    fn new(pp:i32)->Self{ //初始化
        Printer{
            pagerate:pp,
            currentTask : None,
            timeRemaining :0,
        }
    }
    fn tick(&mut self){ //任务执行期间,对已经计算好的执行任务所需时间-1
        if let Some(_) = &self.currentTask{
            self.timeRemaining -=1;
            if self.timeRemaining <= 0{
                self.currentTask = None;
            }
        }
    }
    fn busy(&self) -> bool{ //当前任务不为None,既为繁忙状态
        if let Some(_) = &self.currentTask{
            return true;
        }else{
            return false;
        }
    }
    fn startNext(&mut self,newTask:Task){ 
        //打印新作业,这里剩余时间的计算方式 = 下一个任务需要打印的页数 * 60 / 打印速率
        //假设打印20页,每分钟只能打印5页,也就是说每12秒打印一页,总共需要20*12=240秒
        self.timeRemaining = (newTask.getPages() * 60 / self.pagerate) as i64;
        self.currentTask = Some(newTask);
    }
}
struct Task{
    timestamp : i64,
    pages : i32,
}
impl Task{
    fn new(time:i64)->Self{
        Task{
            timestamp:time, //任务发起的时间
            //随机生成打印页数,范围1张到20张
            pages : rand::thread_rng().gen_range(1, 21), 
        }
    }
    fn getStamp(&self) -> i64{
        self.timestamp
    }
    fn getPages(&self) -> i32{
        self.pages
    }
    fn waitTime(&self,currenttime : i64) -> i64{
        currenttime - self.timestamp //任务等待时间=任务执行的时间-任务发起的时间
    }
}
fn newPrintTask() -> bool{ //新建任务,有1/180的概率发起打印任务
    let mut rng =rand::thread_rng();
    let num : i32 = rng.gen_range(1,181);
    if num == 180{
        return true;
    }else{
        return false;
    }
}
fn simulation(numSeconds:i64,pagersPerminute:i32){
    let mut labprinter = Printer::new(pagersPerminute); //建立一个打印机类实例
    let mut printQueue : Queue = Queue::new(); //建立一个打印任务队列
    let mut waitingtimes : Vec = Vec::new(); //建立一个打印任务的等待时间vec
    for currentSecond in 0..numSeconds{ //开始打印计时
        if newPrintTask(){ //新建任务,有1/180的概率发起打印任务
            let task = Task::new(currentSecond);  //发起成功,建立一个任务类
            printQueue.enqueue(task); //将任务先放入队列
        }
        if !labprinter.busy() && !printQueue.isEmpty(){ //只有打印机不繁忙和任务队列不为空的情况下
            let nextTask : Task = printQueue.dequeue(); //从队列中获取一个新任务
            waitingtimes.push(nextTask.waitTime(currentSecond)); //计算等待时间,并将其push到任务等待vec中
            labprinter.startNext(nextTask); //执行新任务的打印
        }
        labprinter.tick();//时间-1s
    }
    let eee : i64 = waitingtimes.iter().sum(); //合集等待vec中的等待时间
    let averageWait :f64 = (eee / waitingtimes.len() as i64) as f64; //计算平均等待时间
    println!("Average Wait {} secs {} tasks remaining",averageWait,printQueue.size_of()); 
}
pub fn run(){
    for _ in 0..10{ //运行10次模拟
        simulation(3600, 5); //打印1小时,每分钟能打5页
    }
}

Rust数据结构和算法系列[1]-打印机与队列_第2张图片

你可能感兴趣的:(rust,数据结构,算法,队列)