华为机试题:实现一个简易的银行叫号系统

排号机
描述:
实现一个简易的银行排号叫号系统

get 取号 示例:”get”或”get vip”
call 叫号 示例:”call”
delete 删除号码 示例:”delete 5”
count 获取当前排队总人数 示例:”count”
countN 获取号码N以前的排队人数 示例:”countN”
reset 重置排号机 示例:”reset”

quit 退出排号机 示例:”quit”

运行时间限制: 无限制
内存限制: 无限制
输入:
每行只会有一条输入(比如:C语言可使用gets函数获取一行输入命令的字符串)。
1、若输入不符合要求(如:命令字非法,或其他认为输入的错误)均需输出”error”
2、每条输出后使用换行符隔开(如后面示例)

输出:
1)取号。可获取普通号和vip号码。如初始状态,输入”get”,则获取普通号码,执行结果为”1”,如再次输入”get vip”,则获取VIP号码,执行结果为”vip 2”。如果末尾的2号被删除,则再次调用”get”时应输出”2”
VIP号码有绝对的优先级。普通号和vip号码统一编号,取号均为连续号码。号码从1开始编号,最大为100000.

2)叫号。获取当前应该处理用户的号码。例如当前排队号码为1 2 3 4 5 7,当输入”call”,执行结果为”1”,如1为vip号码,则为”vip 1”.如果再连续调用6次,第六次执行结果应为”error”

3)删除号码。客户不想办理时可删除号码,叫号时则跳过此号码。例如当前排队号码为1 2 3 4 5,输入”delete 5”,执行结果为”5”,如果5为vip则显示”vip 5”。再次输出”delete 5”,执行结果为”error”

4)获取当前排队总人数。获取当前排队人数。例如当前排队号码为1 2 3 4 5 6,执行结果为”6”

5)获取在某个号码之前排队的总人数。例如当前排队号码为1 2 3 4 5 7,输入”countN 7”,执行结果为”5”

6、重置排号机。例如输入”reset”,则重置排号机,进入初始状态,无需输出。

7、退出排号机。例如输入”quit”,则退出排号机,无需输出。

样例输入:
get
get
get
get vip
count
countN 1
call
quit
样例输出:
1
2
3
vip 4
4
1
vip 4

我的答案(java):

import java.util.Scanner;
import java.util.TreeSet;


public class Main{

    private final String VIP="vip";

    private long num=1;// 号码 1~100000
    private TreeSet<Long> vipNums=new TreeSet<Long>();// 保存vip号码
    private TreeSet<Long> queue=new TreeSet<Long>();// 队列
    private boolean quit;// 是否退出

    public String[] input(Scanner sc){

        String line=null;
        String[] comd=null;
        try{
            line=sc.nextLine();
            comd=line.split(" ");// 拆分命令
        }catch(Exception e){
//          e.printStackTrace();
            comd=null;
            printError();
        }finally{
//          sc.close();
        }
        return comd;
    }

    public void handle(String[] comd) throws Exception{
        if(comd==null||comd.length==0){
            printError();
        }
        String str=comd[0];// 提取命令

        if(str.equals("get")){

            if(num<1||num>100000){// ERROR
                printError();
            }

            if(comd.length==2){
                String str2=comd[1];
                if(str2.equals(VIP)){// get vip num
                    System.out.println(VIP+" "+num);
                    vipNums.add(num);
                }else{
                    printError();
                }
            }else{
                System.out.println(num);// get common num
            }
            queue.add(num);// 把取的号加入队列
            num++;
        }else if(str.equals("call")){
            Long first=null;
            // vip first
            if(vipNums.size()>0){
                first=vipNums.first();
                System.out.println(VIP+" "+first);
                vipNums.remove(first);
                queue.remove(first);
            }else if(queue.size()>0){
                first=queue.first();
                System.out.println(first);
                queue.remove(first);
            }else{
                printError();
            }
        }else if(str.equals("delete")){
            if(comd.length==2){
                String str2=comd[1];
                Long numToDel=Long.parseLong(str2);
                if(queue.contains(numToDel)){
                    if(vipNums.contains(numToDel)){
                        System.out.println(VIP+" "+numToDel);
                        vipNums.remove(numToDel);
                    }else{
                        System.out.println(numToDel);
                    }
                    if(queue.last().equals(numToDel)){
                        num--;
                    }
                    queue.remove(numToDel);

                }else{
                    printError();
                }
            }else{
                printError();
            }
        }else if(str.equals("count")){
            System.out.println(queue.size());
        }else if(str.equals("countN")){
            if(comd.length==2){
                String str2=comd[1];
                Long numToCount=Long.parseLong(str2);
                if(queue.contains(numToCount)){
                    int count=0;
                    for(Long number : queue){
                        if(number<numToCount){
                            count++;
                        }
                    }
                    System.out.println(count);
                }else{
                    printError();
                }
            }else{
                printError();
            }
        }else if(str.equals("reset")){
            num=1;
            vipNums.clear();
            queue.clear();
        }else if(str.equals("quit")){
            quit=true;
        }else{
            printError();
        }
    }

    public void printError(){
        System.out.println("error");
    }
    public static void main(String[] args){

        Scanner sc=new Scanner(System.in);

        Main m=new Main();

        while(!m.quit){
            String[] comd=m.input(sc);
            try {
                if(comd==null){
                    throw new Exception("comd is null");
                }
                m.handle(comd);
            } catch (Exception e) {
                m.printError();
//              e.printStackTrace();
            }
        }
        sc.close();
    }
}
1.问题的定义即分析 银行叫号系统中大概能分成两个对象:一个为来的顾客,一个为银行本身 顾客(Customer)里面需要包含有数据: 【1】每个顾客都应该有一个标签以用来区分,因此需要一个ID(cID) 【2】问题中有求等待的时间,而有关等待时间的两个变量即为进入银行的时间以及接受服务的时间(enterTime和startTime) 【3】由于题目中说明顾客的服务时间不是固定的,因此每个顾客的服务时间又有区别,所以需要有一个变量来进行表示(serTime) 【4】顾客接受服务完后离开的时间(endTime) 综上:Customer中所需要的私有成员有(cID,enterTime,startTime,serTime,endTime) 而Customer的成员函数其实只是对以上数据进行输入输出,所以有成员函数有: 一系列的Set函数,一系列的Get函数,以及构造函数,复制函数,=的重载函数以及Reset函数 银行(bank)里面需要包含的数据: 银行中的人有两种状态,一是等待,二是接受服务,而这等待状态遵循先到先得的原则,因此,采用队列这种结构来表示这些状态比较合适,已经接受过服务的要反复输入输出,用容易遍历的数据类型vector 【1】处于等待状态的人(waiting) 【2】处于服务状态或已经接受过服务的人(serving) 由于经常要对waiting以及serving进行操作,所以不考虑将其作为私有成员(省去了Set以及Get函数) 考虑一下所含有的成员函数:Reset函数(保证银行是空的),Display函数(对已经接受过服务的以及正在服务的顾客进行展示),Assign()(断某个窗口是否是空的利用每次都改变的endTime - startTime == 随生成的serTime判断 添加功能函数:查看最大等待时间以及其对应的人数的函数Maxwaiting 2.类与算法设计 类设计: class Customer { private: int enterTime; //进入银行的时间 int startTime; //开始服务的时间 int cID; //顾客的编号 int endTime; //顾客停止服务的时间 int serTime; //顾客服务从开始到结束服务所需要的时间(随的) public: Customer(); //默认构造函数 Customer(const Customer &new;_customer); //复制函数 Customer &operator;=(const Customer&old;_customer); //=重载函数 void Reset(); //重置,将所有数据归零 int GetServDurance(); //返回等待时间 int GetEndTime(); //返回离开银行的时间 int GetSerTime(); //返回接受服务的时间 int GetStartTime();//返回开始接受服务的时间 int GetID(); //返回ID void SetEnterTime(int new_enter); void SetStartTime(int new_start); void SetEndTime(int new_end); void SetID(int new_ID); void SetSerTime(int new_sertime); }; class Bank { public: vector<Customer> serving; //在服务窗口接受过服务的人 queue<Customer> waiting; //在银行内等待的人 bool Assign(Customer customer); //判断第i个窗口的顾客是否服务完成 void Display(); //将在等待的人或者是已经接受了服务的人展示到屏幕上 void MaxWaiting(); void Reset(); }; 算法设计 随数的产生: 【1】由于需要对过程进行模拟,所以需要一整套的模拟系统,包括产生随人数,随服务时间等等 【2】事实上,银行对服务窗口的更新是按照一定的时间(即每隔几秒刷新一次),同样的人也是类似,因此需要几个单位时间已确定进行这些随事件发生的间隔 几个变量如下: const int UnitTime = 10;//单位时间为10 const int ServTime = 5;//服务时间为5-10 const int UnitTimePeo = 5;//单位时间进来的人数为5-10; const int StopEnterTime = TimeSlot - 2 * UnitTime;//为了保证所有顾客能完成服务,顾客进入的时间为0-80 const int PerTime = 5;//每隔5秒显示一次窗口信息 int TimeOfServing = 0;//随生成的服务时间(5-10) int Number = 0; //随生成的人数(5-10) 通过这些变量以及srand((unsigned)time(0)),rand()即可产生一系列的随数以便进行模拟 过程的模拟 每当产生一系列随的人,就将他们放进waiting的队列中去,接着遍历各个窗口,若窗口为空,则先来的人可以去那个窗口(即push到serving,pop掉waiting),若不为空,则改变结束时间,之后Present + 1 显示内容:剩余的时间,各窗口的情况,以及已经接受了服务的人的等待时间 注意:该程序为每五刷新一次,每十随进入一些人
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值