数据结构电话客户服务模拟.doc
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 数据结构 电话 客户 服务 模拟
- 资源描述:
-
电话客户服务模拟 一、 问题描述 一个模拟时钟提供接听电话服务的时间(以分钟记),然后这个时钟将循环的自增一(分钟)直到到达指定时间为止。在时钟的每个“时刻”,就会执行一次检查来看看当前电话的服务是否已经完成了,如果是,这个电话从电话队列中删除,模拟服务将从队列中取出下一个电话(如果有的话)继续开始。同时还需要执行一个检查来判断是否有一个新的电话到达。如果是将其到达时间记录下来,并为其产生一个随机服务时间,这个服务时间也被记录下来,然后这个电话被放入电话队列中,当客户服务人员空闲时,按照先来先服务的方式处理这个队列。当时钟到达指定时间时,不会再接听新的电话,但是服务将继续,直到电话队列中所有电话都得到处理为止。当完成上述功能以后,将记录最佳方案,记录客服人员信息,通过桶存储方式来记录和查询信息。 二、 基本要求 (1)程序需要的初始数据包括:客户服务人员的人数,时间限制,电话的到达速率,平均服务时间,客服人员编号,客服人员姓名。 (2)程序产生的结果包括:处理的电话数,每个电话的平均等待时间,服务总时间,限制时间内接听电话数。 三、工具 / 准备工作 在开始做课程设计项目前,应回顾或复习相关内容。 需要一台计算机,期中安装有Visual C++ 6.0、Visual C++ 2005、Visual C++ 2005 Express、Dev-C++或MinGW Developer Studio之一的集成开发环境。 四、 分析与实现 由于要计算客户的等待时间,并且每个客户都有接受服务所需的时间,为实现这些功能,对客户加上当前接受服务的时间,具体客户结构类型和服务人员类型如下: // 服务人员类型 struct TelephoneServerType { char severNumber[18]; // 服务人员编号 char severName[16]; // 服务人员姓名 bool isEmpty; // 是否为空 int objServerTotalTime; //服务总时间 int objTelephoneOfLimit; //限制时间内接听电话数 }; //客户类型 struct CustomerType { unsigned int arrivalTime; //客户到达时刻 unsigned int duration; //客户接受服务所需的时间 unsigned int curServiceTime; //当前接受服务的时间 }; //服务人员类型 struct ServerType { int serverTotalTime; //服务总时间 int telephoneOfLimit; //限制时间内接听电话数 }; 为了模拟计时,在电话客户服务模拟类中增加表示当前时间的变量curTime,此处时间单位为分钟,为更好地模拟,使用泊松随机数,为模拟客户随机打进电话,需要知道客户到达率(平均每分钟打进电话人数),为模拟客户接受服务的时间,需要知道平均服务时间,为存储服务人员信息,需要创造一个文本,将基桶写入文件中,具体客户服务模拟类声明如下: template <int m, int b> TelephoneServer<m, b>::TelephoneServer() // 操作结果: 初始化服务人员信息 { //初始化数据成员 curTime=0; //当前时间初值为0 totalWaitingTime=0; //总等待时间初值为0 numOfCalls=0; //处理的电话数初值为0 //获得模拟参数 cout<<"输入客户人员的人数(请输入数字):"; cin>>numOfCustomerServiceStaffs; //输入客户人员的人数 cout<<"输入时间限制(请输入数字):"; cin>>limitTime; //不再接受新电话的时间 int callsPerHour; //每小时电话数 cout<<"输入每小时电话数(请输入数字):"; cin>>callsPerHour; //输入每小时电话数 arrivalRate=callsPerHour/60.0; //转换为每分钟电话数 cout<<"输入平均服务时间(请输入数字):"; cin>>averageServiceTime; //输入平均服务时间 //分配动态存储空间 callsWaitingQueue=new LinkQueue<CustomerType>[numOfCustomerServiceStaffs]; //为客服电话等待队列数组分配存储空间 customerServed=new CustomerType[numOfCustomerServiceStaffs]; //为客服人员正在服务的客户分配存储空间 servers=new ServerType[numOfCustomerServiceStaffs]; //为服务人员分配存储空间 //初始化客服人员正在服务的客户 for(int i=0; i<numOfCustomerServiceStaffs; i++) { //初始化每个客服人员正在服务的客户 customerServed[i].curServiceTime=customerServed[i].duration=0; //表示还没有人接受服务 servers[i].serverTotalTime=servers[i].telephoneOfLimit=0; //表示还没有工作 } //设置随机数种子 SetRandSeed(); //以当前时间值为随机数种子 ifstream iFile("telph.dat"); // 建立输入文件 if (iFile.fail()) { // 打开文件失败,表示不存在文件 ofstream oFile("telph.dat"); // 建立输出文件 if (oFile.fail()) throw("打开文件失败!"); // 抛出异常 oFile.close(); // 关闭文件 } else { // 存在文件 iFile.close(); // 关闭文件 } hashFile.open("telph.dat", ios::in|ios::out|ios::binary); // 以读写方式打开文件 if (hashFile.fail()) throw("打开文件失败!"); // 抛出异常 hashFile.seekg(0, ios::end); // 定位到文件尾 int bucketNum = hashFile.tellg() / sizeof(BucketType); // 桶数 if (bucketNum < b) { // 桶数不于基桶数,说明文件不完整或已被破坏, 应初始化基桶 BucketType bucket; int pos; // 临时变量 for (pos = 0; pos < m; pos++) { // 初始化基桶 bucket.records[pos].isEmpty = true; // 空记录 bucket.next = -1; // 无溢出 } hashFile.clear(); // 清除标志 hashFile.seekg(0, ios::beg); // 定位到文件头 for (pos = 0; pos < b; pos++) { // 写基桶到文件中 hashFile.write((char *)&bucket, sizeof(BucketType));// 写入基桶 } } } 类TelephoneServer的Service()辅助函数为客户服务人员服务当前的电话,如果当前客户接受服务的时间还未到达客户服务所需的时间,则继续在为客户提供服务,否则如有客户在等待服务,则从等待队列中取出新客户进行服务,并更新总客户等待时间,具体实现如下: template <int m, int b> void TelephoneServer<m, b>::Service() //操作结果:服务当前电话(如有电话) { for(int i=0;i<numOfCustomerServiceStaffs;i++) { //处理每个客服工作人员提供的服务 if(customerServed[i].curServiceTime<customerServed[i].duration) { //未到达客户接受服务所需的时间,正在为客户提供服务 customerServed[i].curServiceTime++; //增加客户接受服务的时间 } else { //已到达客户接受服务所需的时间,为下一客户提供服务 if(!callsWaitingQueue[i].Empty()) { //有客户在等待 callsWaitingQueue[i].OutQueue(customerServed[i]); //从等待队列中取出新客户进行服务 totalWaitingTime+=curTime-customerServed[i].arrivalTime; //更新总客户等待时间 } } } } 类TelephoneServer的CheckForNewCall()辅助函数用于生成当前时间打进电话的人数,对每个打进电话的客户,将其插入最短的客服电话等待队列中,具体实现如下: template <int m, int b> void TelephoneServer<m, b>::CheckForNewCall() //操作结果:检查是否有新电话,如果有,则将电话添加到电话队列 { int calls=GetPoissionRand(arrivalRate); //当前打进电话的人数 for(int i=1;i<=calls;i++) { //第i个电话 CustomerType customer; //客户 customer.arrivalTime=curTime; //客户到达时间 customer.duration=GetPoissionRand(averageServiceTime); //客户接受服务所需的时间 customer.curServiceTime=0; //当前接受服务的时间 int pos=MinLengthCallWaitingQueue(); //最短客服电话等待队列的位置 callsWaitingQueue[pos].InQueue(customer); //客户插入等待队列 numOfCalls++; //处理的电话数 } } 类TelephoneServer的Display()辅助函数用于在模拟的最后显示处理的总电话数和每个电话的平均等待时间,具体实现如下: template <int m, int b> void TelephoneServer<m, b>::Display() //操作结果:显示模拟结果 { cout<<"处理的总电话数:"<<numOfCalls<<endl; cout<<"平均等待时间:"<<GetTheAverageServiceTimet()<<endl<<endl; } 类TelephoneServer的Run()方法实现模拟电话客户服务,当为到达时间限制时,首先检查是否有新电话,如果有,则将电话添加到电话队列,然后客户服务人员再对当前客户进行服务,最后增加时间;当已到达时间限制时,不再检查是否有新电话,但客户服务人员还要对当前客户进行服务,并增加时间,具体实现如下: template <int m, int b> void TelephoneServer<m, b>::Run() //操作结果:模拟电话客户服务 { while(curTime<limitTime) { //未到达时间限制,可检查新电话 CheckForNewCall(); //检查是否有新电话,如果有,则将电话添加到电话队列 Service(); //进行服务 curTime++; //增加时间 } while(MinLengthCallWaitingQueue()>0) { //在客服电话等待队列中还有客户在等待服务 Service(); //进行服务 curTime++; //增加时间 } Display(); } 类TelephoneServer中Hash(const char severNumber[18])辅助函数用于生成散列函数值,具体实现如下: template <int m, int b> long TelephoneServer<m, b>::Hash(const char severNumber[18]) // 操作结果: 返回散列函数值 { long h = 0; // 散列函数值 for (int pos = 0; pos < (int)strlen(severNumber); pos++) { // 依次处理各数字字符 h = (h * 10 + severNumber[pos] - '0') % b; } return h; // 返回散列函数值 } 类TelephoneServer中LocateHelp(const BucketType &bucket, char severNumber[18])辅助函数用于记录服务人员编号在桶中的位置,具体实现如下: template <int m, int b> int TelephoneServer<m, b>::LocateHelp(const BucketType &bucket, char severNumber[18]) // 操作结果: 返回服务人员编号severNumber在桶bucket中的位置 { for (int pos = 0; pos < m; pos++) { // 依次比较桶中各服务人员信息存储记录 if (!bucket.records[pos].isEmpty && strcmp(bucket.records[pos].severNumber, severNumber) == 0) return pos; // 定位成功 } return -1; // 定位失败 } 类TelephoneServer中Locate(BucketType &bucket, long &offset,int &pos, char severNumber[18])辅助函数用于定位服务人员编号所在的桶,以及在桶中的位置和桶在文件中的位置,具体实现如下: template <int m, int b> void TelephoneServer<m, b>::Locate(BucketType &bucket, long &offset, int &pos, char severNumber[18]) // 操作结果: 定位服务人员编号severNumber所在的桶bucket, 在桶中的位置pos, 桶在文件 // 中的位置位置offset { long h = Hash(severNumber); // 散列函数值 offset = sizeof(BucketType) * h; // 桶在文件中的位置 hashFile.clear(); // 清除标志 hashFile.seekg(offset, ios::beg); // 文件定位 hashFile.read((char *)&bucket, sizeof(BucketType)); // 读取基桶 pos = LocateHelp(bucket, severNumber); // 定位服务人员信息存储记录在桶中的位置 if (pos == -1) offset = bucket.next; // 溢出桶的位置 while (pos == -1 && offset != -1) { // 继续在溢出桶中查找 hashFile.clear(); // 清除标志 hashFile.seekg(offset, ios::beg); // 文件定位 hashFile.read((char *)&bucket, sizeof(BucketType)); // 读到基桶 pos = LocateHelp(bucket, severNumber); // 定位服务人员信息存储记录在桶中的位置 if (pos == -1) offset = bucket.next; // 后继溢出桶的位置 } } 类TelephoneServer中LocateEmptyRecordHelp(const BucketType &bucket)辅助函数用于获得空记录的位置,具体实现如下: template <int m, int b> int TelephoneServer<m, b>::LocateEmptyRecordHelp(const BucketType &bucket) // 操作结果: 返回空记录位位置 { for (int pos = 0; pos < m; pos++) { // 依次比较桶中各服务人员信息存储记录 if (bucket.records[pos].isEmpty) return pos; // 定位成功 } return -1; // 定位失败 } 类TelephoneServer中LocateEmptyRecord(BucketType &bucket, long &offset, int &pos, char severNumber[18])辅助函数用于服务人员编号所在具有空记录的桶,以及桶中空记录的位置,和桶在文件中的位置,具体实现如下: template <int m, int b> void TelephoneServer<m, b>::LocateEmptyRecord(BucketType &bucket, long &offset, int &pos, char severNumber[18]) // 操作结果: 定位服务人员编号severNumber所在的具有空记录的桶bucket, 桶中的空记录位置pos, 桶 // 在文件中的位置位置offset { long h = Hash(severNumber); // 散列函数值 offset = sizeof(BucketType) * h; // 桶在文件中的位置 hashFile.clear(); // 清除标志 hashFile.seekg(offset, ios::beg); // 文件定位 hashFile.read((char *)&bucket, sizeof(BucketType)); // 读到基桶 pos = LocateEmptyRecordHelp(bucket); // 定位桶中空记录的位置 if (pos == -1) offset = bucket.next; // 溢出桶的位置 while (pos == -1 && offset != -1) { // 继续在溢出桶中查找 hashFile.clear(); // 清除标志 hashFile.seekg(offset, ios::beg); // 文件定位 hashFile.read((char *)&bucket, sizeof(BucketType)); // 读到基桶 pos = LocateEmptyRecordHelp(bucket); // 定位桶中空记录的位置 if (pos == -1) offset = bucket.next; // 后继溢出桶的位置 } } 类TelephoneServer中Input()辅助函数用于输入记录并且将数据写入通过桶写入到文件中,具体实现如下: template <int m, int b> void TelephoneServer<m, b>::Input() // 操作结果: 输入记录 { TelephoneServerType telph; // 服务人员信息存储记录 telph.isEmpty = false; // 标记 cout << "输入服务人员编号:"; cin >> telph.severNumber; cout << "输入服务人员姓名:"; cin >> telph.severName; telph.objServerTotalTime=GetTheServerTotalTime(); telph.objTelephoneOfLimit=GetTheTelephoneOfLimit(); BucketType bucket; // 桶 long offset; // 桶在文件中的相应位置 int pos; // 服务人员信息存储记录在桶中的位置 Locate(bucket, offset, pos, telph.severNumber); // 定位服务人员信息存储记录的位置 if (pos != -1) { // 定位成功 cout << "编号已在散列文件中!" << endl; } else { // 定位失败 LocateEmptyRecord(bucket, offset, pos, telph.severNumber);// 定位空记录位置 if (pos != -1) { // 找到空记录 bucket.records[pos] = telph; // 将服务人员信息存储记录赋值给bucket.records[pos] hashFile.clear(); // 清除标志 hashFile.seekg(offset, ios::beg); // 定位文件 hashFile.write((char *)&bucket, sizeof(BucketType));// 写桶 } else { hashFile.clear(); // 清除标志 hashFile.seekg(0, ios::end); // 定位到文件尾 bucket.next = hashFile.tellg(); // 后继溢出桶位置 hashFile.clear(); // 清除标志 hashFile.seekg(offset, ios::beg); // 定位文件 hashFile.write((char *)&bucket, sizeof(BucketType));// 写桶 offset = bucket.next; // 新溢出桶在文件中的位置 for (pos = 1; pos < m; pos++) { // 设置空记录 bucket.records[pos].isEmpty = true; } pos = 0; // 服务人员信息存储记录的位置 bucket.records[pos] = telph; // 将服务人员信息存储记录赋值给bucket.records[pos] hashFile.clear(); // 清除标志 hashFile.seekg(offset, ios::beg); // 定位文件 hashFile.write((char *)&bucket, sizeof(BucketType));// 写桶 } } } 类TelephoneServer中Serach()辅助函数用于查找客服人员的信息,通过输入客服人员编号获得其在文件中的位置并显示在屏幕上,具体实现如下: template <int m, int b> void TelephoneServer<m, b>::Serach() // 操作结果: 查找记录 { char severNumber[18]; // 服务人员编号 cout << "输入服务人员编号:"; cin >> severNumber; BucketType bucket; // 桶 long offset; // 桶在文件中的相应位置 int pos; // 服务人员信息存储记录在桶中的位置 Locate(bucket, offset, pos, severNumber);// 定位服务人员信息存储记录的= -1) if (pos == -1) { // 定位失败 cout << "查找失败!" << endl; } else { hashFile.clear(); // 清除标志 hashFile.seekg(offset, ios::beg); // 定位文件 hashFile.read((char *)&bucket, sizeof(BucketType)); // 读桶 cout << "服务人员编号:" << bucket.records[pos].severNumber << endl; cout << "服务人员姓名:" << bucket.records[pos].severName << endl; cout << "服务总时间:" << bucket.records[pos].objServerTotalTime << endl; cout << "限制时间内接听电话数:" << bucket.records[pos].objTelephoneOfLimit << endl; } } 类TelephoneServer中ServerRun()辅助函数用于处理客服人员信息,通过获得相应的信息,从而链接文本中的桶,具体实现如下: template <int m, int b> void TelephoneServer<m, b>::ServerRun() // 操作结果: 处理服务人员信息 { int select; // 临时变量 do { cout << "1.输入信息 2.查找信息 3.退出" << endl; cout << "输入选择:"; cin >> select; // 输入选择 while (GetChar() != '\n'); // 跳过当前行的其它字符 switch (select) { case 1: Input(); // 输入记录 break; case 2: Serach(); // 查找记录 break; } } while (select != 3); } 五、 测试与结论 测试时,假设时间限制为600(分钟),每小时电话数为60,平均服务时间为1(分钟),对不同客服人员人数进行模拟如下: 综合可知,当有3个客服人员是比较恰当的,故开始记录客服人员信息。 六、 课程设计总结 主要是对于信息记录的扩展。首先是计算最佳服务方式需要的客服人员人数;当接近平均等待时间为1(分钟)时,此时开始记录客服人员信息,信息内容有客服人员编号和姓名。该功能是通过桶存储方式写入到文本中,然后以客服人员编号为比较信息在存储文本里查找和写入。另外还有就是计算客服人员的客服人员服务总时间和在限制时间内接听电话数,并且将该数据加入到服务人员类型里面,然后通过函数传递的方式传递,然后写入桶中,在查找信息的时候随其他信息输出。在完成该功能的过程中,我是在桶一文件中声明了两个类,但是在传递数据的时候有错误,就是在其中一个类中是正确的数据,但是我是把该数据加入到加入到客户类型里,然后通过该结构变量调用,但是传递到另一个类中的数据就是乱码,我也不知道怎么回事。通过自己手动编写这个项目,体会到自己的要学的还很多,另外就是熟悉了以前所不熟悉的一些知识,比如结构的使用,还有链表的使用等等,我相信多动手会让我收获更多。展开阅读全文
咨信网温馨提示:1、咨信平台为文档C2C交易模式,即用户上传的文档直接被用户下载,收益归上传人(含作者)所有;本站仅是提供信息存储空间和展示预览,仅对用户上传内容的表现方式做保护处理,对上载内容不做任何修改或编辑。所展示的作品文档包括内容和图片全部来源于网络用户和作者上传投稿,我们不确定上传用户享有完全著作权,根据《信息网络传播权保护条例》,如果侵犯了您的版权、权益或隐私,请联系我们,核实后会尽快下架及时删除,并可随时和客服了解处理情况,尊重保护知识产权我们共同努力。
2、文档的总页数、文档格式和文档大小以系统显示为准(内容中显示的页数不一定正确),网站客服只以系统显示的页数、文件格式、文档大小作为仲裁依据,个别因单元格分列造成显示页码不一将协商解决,平台无法对文档的真实性、完整性、权威性、准确性、专业性及其观点立场做任何保证或承诺,下载前须认真查看,确认无误后再购买,务必慎重购买;若有违法违纪将进行移交司法处理,若涉侵权平台将进行基本处罚并下架。
3、本站所有内容均由用户上传,付费前请自行鉴别,如您付费,意味着您已接受本站规则且自行承担风险,本站不进行额外附加服务,虚拟产品一经售出概不退款(未进行购买下载可退充值款),文档一经付费(服务费)、不意味着购买了该文档的版权,仅供个人/单位学习、研究之用,不得用于商业用途,未经授权,严禁复制、发行、汇编、翻译或者网络传播等,侵权必究。
4、如你看到网页展示的文档有www.zixin.com.cn水印,是因预览和防盗链等技术需要对页面进行转换压缩成图而已,我们并不对上传的文档进行任何编辑或修改,文档下载后都不会有水印标识(原文档上传前个别存留的除外),下载后原文更清晰;试题试卷类文档,如果标题没有明确说明有答案则都视为没有答案,请知晓;PPT和DOC文档可被视为“模板”,允许上传人保留章节、目录结构的情况下删减部份的内容;PDF文档不管是原文档转换或图片扫描而得,本站不作要求视为允许,下载前可先查看【教您几个在下载文档中可以更好的避免被坑】。
5、本文档所展示的图片、画像、字体、音乐的版权可能需版权方额外授权,请谨慎使用;网站提供的党政主题相关内容(国旗、国徽、党徽--等)目的在于配合国家政策宣传,仅限个人学习分享使用,禁止用于任何广告和商用目的。
6、文档遇到问题,请及时联系平台进行协调解决,联系【微信客服】、【QQ客服】,若有其他问题请点击或扫码反馈【服务填表】;文档侵犯商业秘密、侵犯著作权、侵犯人身权等,请点击“【版权申诉】”,意见反馈和侵权处理邮箱:1219186828@qq.com;也可以拔打客服电话:0574-28810668;投诉电话:18658249818。




数据结构电话客户服务模拟.doc



实名认证













自信AI助手
















微信客服
客服QQ
发送邮件
意见反馈



链接地址:https://www.zixin.com.cn/doc/10698869.html