一、簡單介紹
這是在博客園潛水幾個月第一次開始想要寫點東西,一是記錄自己的學習過程,二是和大家分享同時接受大家的指正,再者可以多交一些朋友,我微博地址在公告欄里。。。。這是最近上數據結構時的練習題,首先是隊列的實現,再用隊列去模擬解決一個實際問題——輪渡模擬。
二、問題分析
2.1 問題描述:
- 輪渡模擬:有一個渡口,每條渡船能一次性裝載10輛汽車過河,車輛分為客車和貨車兩類。
- 上渡輪有如下規定:同類汽車先到先上船,客車先於貨車上船,輪渡每10分鍾一班。
- 模擬一小時內汽車上渡輪的過程。
- 汽車:包含一個汽車類型屬性,一個到達時間屬性,到達時間隨機產生。
- 輪渡:包含一個裝車情況的屬性,一個出發時間的屬性。
- 輸出:1小時內六班輪渡的裝車情況。
2.2 實現說明:
- 輪渡不管是否裝滿10秒鍾一班,一共進行6班共一分鍾;
- 期間的汽車到來時間及類型是隨機的;
- 初始當前已有一班渡輪停靠在渡口;
當拿到這個問題時,分析問題后覺得要比較好的使各個事件不相互影響地模擬輪渡情況,需要用到多線程,但因為以前都是在Linux環境下編程,沒有在Windows上實現過多線程編程,所以也不知道在具體實現中是否會存在什么問題。實現時在主函數中創建了三個線程:其中兩個線程分別是客車和貨車隨機產生(到達),並攜帶時間信息進入到相應的隊列;還有一個是用於做計時器用。

三、實現代碼
3.1測試
#include <iostream> #include <ctime> #include <cstdlib> #include <windows.h> #include <process.h> #include "sqQueue.h" //包含自定義隊列類 using namespace std; #define MAX_NUM 10 //渡輪最大裝載數量 typedef enum{PassengerCar, FreightCar}CarType; //汽車類型 typedef struct { CarType type; //汽車類型 time_t arriveTime; //汽車到達時間 }Car; typedef struct { int size; //渡輪當前裝載汽車數量 time_t startTime; //渡輪出發時間 }Ferry; SqQueue<Car> pCarQueue(61); //定義隊列,用於存放客車的隊列,模擬一分鍾最多60輛汽車 SqQueue<Car> fCarQueue(61); //定義隊列,用於存放貨車的隊列 int startTimeFlag = 0; //定義渡輪出發標志 int countLength = 6; //計數長度 unsigned _stdcall threadCountFun(void* pArguments) { while (countLength > 0) { Sleep(10000); //計數10秒 startTimeFlag = 1; countLength--; } return 0; }
bool ferryFun() //函數:處理渡輪到達,裝載,出發等 { int count = 1; //渡輪計數 while (count<7) { Ferry ferry; ferry.size = 0; //初始輪渡裝載汽車數量 while(1) { if (ferry.size < 10 ) //輪渡未滿 { if (!pCarQueue.isEmpty_SqQueue() && !fCarQueue.isEmpty_SqQueue() && pCarQueue.top_SqQueue().arriveTime == fCarQueue.top_SqQueue().arriveTime) { //當兩隊列對頭汽車到達時間相同時,客車先上船 cout<<"一輛客車上船...其到達渡口時間:"; cout<<ctime(&pCarQueue.top_SqQueue().arriveTime); pCarQueue.pop_SqQueue(); ferry.size++; }
else if (!pCarQueue.isEmpty_SqQueue() && !fCarQueue.isEmpty_SqQueue() && pCarQueue.top_SqQueue().arriveTime < fCarQueue.top_SqQueue().arriveTime) { //客車先到 cout<<"一輛客車上船...其到達渡口時間:"; cout<<ctime(&pCarQueue.top_SqQueue().arriveTime); pCarQueue.pop_SqQueue(); ferry.size++; }
else if(!fCarQueue.isEmpty_SqQueue()) //貨車先到 { cout<<"一輛貨車上船...其到達渡口時間:"; cout<<ctime(&fCarQueue.top_SqQueue().arriveTime); fCarQueue.pop_SqQueue(); ferry.size++; } }
if (1 == startTimeFlag) { time(&ferry.startTime); cout<<"時間過去"<<10*count<<"分鍾"; cout<<"第"<<count<<"條渡輪開走,"<<"裝有汽車"; cout<<ferry.size<<"輛"<<",出發時間:"<<ctime(&ferry.startTime); count++; startTimeFlag = 0; break; }
} }
return true; } unsigned _stdcall threadPCarFun(void* pArguments) //客車處理函數 { srand(time(0)); while (!pCarQueue.isFull_SqQueue()) { Car car; if (1 == rand()%14) //1(客車) { car.type = PassengerCar; time(&car.arriveTime); //記錄到達時間 pCarQueue.push_SqQueue(car); // cout<<"P: "<<car.arriveTime<<endl; } Sleep(200); //200和10意義:每2毫秒中有十四分之一概率產生(到達)一輛汽車(客車和貨車) } return 0; } unsigned _stdcall threadFCarFun(void* pArguments) //貨車處理函數 { srand(time(0)); while (!fCarQueue.isFull_SqQueue()) { Car car; if(2 == rand()%14) //2(貨車) { car.type = FreightCar; time(&car.arriveTime); //記錄到達時間 fCarQueue.push_SqQueue(car); // cout<<"H: "<<car.arriveTime<<endl; } Sleep(200); //200和14意義:每1毫秒中有十分之一概率產生(到達)一輛汽車 } //測試這個頻率能看到裝滿和沒裝滿的情況 return 0; } int main(int argc, char** argv) { HANDLE hThread_P, hThread_F, hThread_Count; unsigned int threadID_P, threadID_F, threadID_Count; hThread_P = (HANDLE) _beginthreadex(NULL, 0, &threadPCarFun, NULL, 0, &threadID_P); hThread_F = (HANDLE) _beginthreadex(NULL, 0, &threadFCarFun, NULL, 0, &threadID_F); hThread_Count = (HANDLE) _beginthreadex(NULL, 0, &threadCountFun, NULL, 0, &threadID_Count); ferryFun(); cout<<"\n汽車排隊中....直至隊滿..."<<endl; WaitForSingleObject(hThread_P, INFINITE ); WaitForSingleObject(hThread_F, INFINITE ); WaitForSingleObject(hThread_Count, INFINITE );
CloseHandle(hThread_P); CloseHandle(hThread_F); CloseHandle(hThread_Count); return 0; }
運行結果:

3.2以下是自己用模板類實現的循環隊列:
自定義隊列類(sqQueue.h)
#ifndef SQQUEUE_H #define SQQUEUE_H #define Q_MAX_LENGTH 100 template <typename T> class SqQueue { public: SqQueue(int length_SqQueue = Q_MAX_LENGTH); virtual ~SqQueue(); bool push_SqQueue(const T& e); bool pop_SqQueue(); bool isEmpty_SqQueue(); bool isFull_SqQueue(); T& top_SqQueue(); const T& top_SqQueue()const; int size_SqQueue(); void display_SqQueue(); private: T* data; int front; int rear; int length; }; /*構造函數,初始化隊列*/ template <typename T> SqQueue<T>::SqQueue(int length_SqQueue) { data = new T[length_SqQueue]; front = rear = 0; length = length_SqQueue; } /*析構函數*/ template <typename T> SqQueue<T>::~SqQueue() { delete []data; } /*判空操作 */ template <typename T> bool SqQueue<T>::isEmpty_SqQueue() { if (front == rear) return true; else return false; } /*判滿操作*/ template <typename T> bool SqQueue<T>::isFull_SqQueue() { if ((rear+1)%length == front) return true; else return false; } /*入隊操作*/ template <typename T> bool SqQueue<T>::push_SqQueue(const T& e) { if (!isFull_SqQueue()) { data[rear] = e; rear = (rear+1)%length; return true; } return false; } /*出隊操作*/ template <typename T> bool SqQueue<T>::pop_SqQueue() { if (!isEmpty_SqQueue()) { front = (front+1)%length; } return false; } /*得到對頭元素*/ template <typename T> T& SqQueue<T>::top_SqQueue() { if (!isEmpty_SqQueue()) { return data[front]; } // cout<<"隊列空"<<endl; } /*得到對頭元素, const版本*/ template <typename T> const T& SqQueue<T>::top_SqQueue()const { if (!isEmpty_SqQueue()) { return data[front]; } // cout<<"隊列空"<<endl; } /*測隊長*/ template <typename T> int SqQueue<T>::size_SqQueue() { return (rear-front+length)%length; } /*遍歷打印操作*/ template <typename T> void SqQueue<T>::display_SqQueue() { int i = front; while (i != rear) { std::cout<<data[i]<<" "; i = (i+1)%length; } std::cout<<endl; } #endif
