Rust數據結構和算法系列[1]-打印機與隊列

最近在B站學習了北京大學的北京大學-數據結構與算法Python版 https://www.bilibili.com/video/BV1TJ411Q7zL

由於同時還在學習rust,所以突然想將其裏面的數據結構和算法用rust實現一遍

準備一步步來,這次先實現一個教案中的打印機任務模擬,仿照原版的python代碼先依樣畫葫蘆

 

//一步步來先用最簡單的vec包裝一個Queue
pub struct Queue<T>{
    data : Vec<T>,
}
impl<T> Queue<T>{
    pub fn new() -> Queue<T>{
        let mut data : Vec<T> = 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<Task>, //當前任務,這裏用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<Task> = Queue::new(); //建立一個打印任務隊列
    let mut waitingtimes : Vec<i64> = 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頁
    }
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章