一、简单介绍
这是在博客园潜水几个月第一次开始想要写点东西,一是记录自己的学习过程,二是和大家分享同时接受大家的指正,再者可以多交一些朋友,我微博地址在公告栏里,互粉哦。。。。这是最近上数据结构时的练习题,首先是队列的实现,再用队列去模拟解决一个实际问题——轮渡模拟。
二、问题分析
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