一、先來先服務
#define _CRT_SECURE_NO_WARNINGS#include <iostream>#include <new>#include <string>#include <cstdio>using namespace std;unsigned int sysTime = 0;// 類比系統的時鐘,每運行一次就加1enum Status {Ready, Complete};// 就緒態Ready,完成態Completeclass PCB{public:// 許可權待改進string name;Status condition;// 進程當前的狀態unsigned int arriveTime;// 到達時間unsigned int serveTime;// 服務時間,每執行一次減1,是變化的unsigned int serveTimeConst;// serveTime運行一次減1,因為最後要算帶權周轉時間,故用serveTimeConst來儲存初始的serveTimeunsigned int startTime;// 開始執行時間unsigned int endTime;// 完成時間unsigned int T;// 周轉時間turnaroundTimedouble W;// 帶權周轉時間weightedTurnaroundTimePCB *next;// 建構函式PCB(string _name = "", unsigned int _arriveTime = 0, unsigned int _serveTime = 0):name(_name),condition(Ready),arriveTime(_arriveTime),serveTime(_serveTime),serveTimeConst(_serveTime),startTime(0),endTime(0),T(0),W(0),next(NULL){}};class ReadyQueue{public:PCB *head;// 頭指標指向頭結點PCB *tail;// 指向尾結點// 建構函式ReadyQueue(){head = new(nothrow) PCB();// 帶頭結點的鏈隊列if (NULL == head){cout << "StackOverflow!" << endl;exit(-1);}tail = head;// 設尾指標,初始化為頭指標}// 輸入所有進程void Input(){cout << "請輸入各進程名、到達時間及估計服務時間:" << endl;string name;unsigned int arrT;unsigned int serT;while (cin >> name >> arrT >> serT){EnQueue(name, arrT, serT);// 在就緒隊列Q中插入剛來的進程}}// PCB入隊,用進程的到達時間和服務時間來初始化void EnQueue(string _name, unsigned int _arriveTime, unsigned int _serveTime){PCB *p = new(nothrow) PCB(_name, _arriveTime, _serveTime);if (NULL == p){cout << "StackOverflow!" << endl;exit(-1);}tail->next = p;tail = tail->next;}// 判空bool IsEmpty(){return head == tail;}// 執行隊首進程void Run(){if (IsEmpty()){cout << "隊列為空白,不能執行!" << endl;exit(-1);}cout << "就緒隊列:";// 不空則先輸出所有就緒進程for (PCB *q = head->next; q != NULL; q = q->next){cout << q->name;if (q != this->tail){cout << "->";}}PCB *p = head->next;// 取出將要執行的進程while (sysTime < p->arriveTime)// 若此時進程“還未到達”,則等待(這個最好在入隊時判斷,但入隊和出隊應並發執行,待改進){++sysTime;}p->startTime = sysTime;cout << "\n進程" << p->name << "開始運行,估計服務時間為" << p->serveTime << ",此時系統時間為:" << sysTime << endl;cout << "已已耗用時間\t剩餘已耗用時間" << endl;while (p->serveTime != 0)// 執行{++sysTime;--(p->serveTime);// 類比服務時間-1操作cout << sysTime - p->startTime << "\t\t"<< p->serveTime << endl;}// 退出執行時服務時間為0,而serveTimeConst儲存了初始的服務時間,以便算帶權周轉時間cout << "進程" << p->name << "執行完畢!" << endl << endl;p->condition = Complete;p->endTime = sysTime;p->T = p->endTime - p->arriveTime;p->W = (double)(p->T) / p->serveTimeConst;// 注意類型轉換}// 刪除隊首進程,返回該進程的地址PCB* DeQueue(){if (IsEmpty())// 判空{cout << "隊空,不得刪除!" << endl;exit(-1);//return NULL;}PCB *p = head->next;head->next = p->next;if (tail == p)// 最後一個進程出隊時要特別注意{tail = head;}return p;//不釋放結點,因為最後要輸出所有結點的資訊}// 解構函式~ReadyQueue()// 後面的結點由StorePCB釋放{delete head;head = NULL;}};class StorePCB{public:PCB *front;PCB *rear;// 建構函式StorePCB(){front = new(nothrow) PCB();// 帶頭結點的鏈隊列if (NULL == front){cout << "StackOverflow!" << endl;exit (-1);}rear = front;// 設尾指標,初始化為頭指標}// 輸出所有進程資訊void Output(){cout << "各進程資訊:\n進程名\t周轉時間\t帶權周轉時間" << endl;for (PCB *p = front->next; p != NULL; p = p->next){cout << p->name << "\t"<< p->T << "\t\t"<< p->W << endl;}}// 把p指向的PCB插入Svoid EnQueue(PCB *p){if (p == NULL){cout << "不能向儲存隊列中插入空!" << endl;exit (-1);}p->next = NULL;// 重要,以便最後釋放rear->next = p;rear = rear->next;}// 解構函式~StorePCB(){PCB *p = NULL;PCB *q = NULL;for (p = front; p != NULL; p = q){q = p->next;delete p;p = NULL;}front = NULL;rear = NULL;}};int main(int argc, char **argv){//freopen("cin.txt", "r", stdin);//freopen("cout.txt", "w", stdout);ReadyQueue Q;// 就緒隊列QStorePCB S;// S用於儲存執行完畢的進程(修改指標即可)unsigned int count = 1;// 輸入進程Q.Input();// 執行進程while (!Q.IsEmpty())// 只要就緒隊列不為空白就一直執行{cout << "*********************************** Case " << count++ << " ***********************************" << endl;Q.Run();// 執行就緒隊首進程PCB *tmp = Q.DeQueue();// 得到剛執行完畢的進程的地址S.EnQueue(tmp);// 將執行完畢的進程儲存在S中}cout << "***************************** 進程全部執行完畢! *****************************" << endl << endl;// 輸出進程的執行資訊(周轉時間和帶權周轉時間)S.Output();return 0;}
二、搶佔式動態優先權
#define _CRT_SECURE_NO_WARNINGS#include <iostream>#include <new>#include <queue>#include <string>#include <cstdio>using namespace std;unsigned int sysTime = 0;// 類比系統的時鐘,每運行一次就加1enum Status {Ready, Complete};// 就緒態Ready,完成態Completeclass PCB{public:// 許可權待改進unsigned int priorityNum;// 優先數(優先數越大,優先權越低,0表示最高優先權)string name;// 進程名Status condition;// 當前的狀態unsigned int arriveTime;// 到達時間unsigned int serveTime;// 服務時間(每執行一次減1,是變化的)unsigned int serveTimeConst;// serveTime運行一次減1,因為最後要算帶權周轉時間,故用serveTimeConst來儲存初始的serveTimeunsigned int startTime;// 開始執行時間unsigned int endTime;// 完成時間unsigned int T;// 周轉時間turnaroundTimedouble W;// 帶權周轉時間weightedTurnaroundTimePCB *next;// 指向下個PCB// 建構函式PCB(string _name = "",unsigned int _arriveTime = 0,unsigned int _serveTime = 0,unsigned int _priorityNum = 0):name(_name),condition(Ready),arriveTime(_arriveTime),serveTime(_serveTime),serveTimeConst(_serveTime),startTime(0),endTime(0),T(0),W(0),next(NULL),priorityNum(_priorityNum){}// 比較優先順序,優先數bool operator<(const PCB &obj) const{return this->priorityNum > obj.priorityNum;// 規定優先順序與優先數相反}};// 執行隊首進程一次void Run(priority_queue<PCB> &Q){if (Q.empty()){cout << "隊列為空白,不能執行!" << endl;exit(-1);}cout << "就緒隊列:";priority_queue<PCB> myQ(Q);// 要輸出優先隊列,只能每次都輸出隊首,故建立一個副本while (!myQ.empty()){cout << myQ.top().name;myQ.pop();if (!myQ.empty()){cout << " -> ";}}cout << endl;PCB head(Q.top());// 優先隊列不能對其隊首直接修改?Q.pop();//head.startTime = sysTime;// 開始執行時間無意義?sysTime++;head.priorityNum++;head.serveTime--;if (head.serveTime == 0)// 運行完畢{cout << "進程" << head.name << "執行完畢" << endl;head.condition = Complete;head.endTime = sysTime;head.T = head.endTime - head.arriveTime;head.W = (double)(head.T) / head.serveTimeConst;}else{Q.push(head);}}int main(int argc, char **argv){freopen("cin.txt", "r", stdin);priority_queue<PCB> Q;// ReadyQueuestring name;unsigned int arrT;unsigned int serT;unsigned int priorityNum;// 輸入進程cout << "請輸入各進程名、到達時間及估計服務時間:" << endl;while (cin >> name >> arrT >> serT >> priorityNum){Q.push(PCB(name, arrT, serT, priorityNum));// 在就緒隊列Q中插入剛來的進程}cout << endl;while (!Q.empty()){Run(Q);// 運行一次}return 0;}