7.11.1 Double Queue

任务描述

新成立的巴尔干投资集团银行(Balkan Investment Group Bank (BIG-Bank))在布加勒斯特开设了一个新的办事处,配备了 IBM Romania 提供的现代计算环境,并使用了现代信息技术。与往常一样,银行的每个客户都用一个正整数K 来标识,在客户到银行办理业务时,他或她会收到一个正整数优先级 P 。银行的年轻管理人员的一项发明让银行服务系统的软件工程师非常吃惊。他们要打破传统,有时,服务台叫具有最低优先级的客户,而不是叫最高优先级的客户。因此,系统将接收以下类型的请求:

0系统需要停止服务
1 K P将客户K添加等待列表中,其优先级为P
2服务具有最高优先级的客户,并将其从等待名单中删除
3服务具有最低优先级的客户,并将其从等待名单中删除

请您编写一个程序,帮助银行的软件工程师实现所要求的服务策略。

编程要求

根据提示,在右侧编辑器补充代码,完成数据测试并通过。

测试说明

输入说明

每行输入给出一个可能的请求;只有在最后一行给出停止请求(代码0)。本题设定,当有一条请求是在等待列表中加入一个新客户时(代码1),在列表中不会有其他的请求加入相同的客户或相同的优先级。标识符 K 总是小于106,优先级P小于107。客户可以多次办理业务,并且每次的优先级可以不同。

输出说明

对于代码为23的每个请求,您的程序要以标准输出的方式,在单独的一行中输出要服务的客户的标识符。如果发出请求时等待列表为空,则程序输出零(0)。 平台会对你编写的代码进行测试:

测试输入:

 
  1. 2
  2. 1 20 14
  3. 1 30 3
  4. 2
  5. 1 10 99
  6. 3
  7. 2
  8. 2
  9. 0

预期输出:

 
  1. 0
  2. 20
  3. 30
  4. 10
  5. 0
    #include <cstdio>
    #include <cstdlib>
    using namespace std;
    struct Node
    {
        Node *ch[2];                                 //左右指针
        int r,v,info;                                //v是顾客优先级,info是顾客的编号,r由rand()生成
        Node(int v,int info):v(v),info(info)         //产生一个叶节点,顾客优先级v,顾客编号info,随机产生节点优先级r,左右指针空
        {
            r=rand();                               //随机产生节点优先级
            ch[0]=ch[1]=NULL;                       //左右指针空
    
        }
        int cmp(int x)                           //顾客优先级v与x比较大小cmp(x)={-1(x=v);0(x<v);1(x>v)}
        {
            if(x==v)return -1;
            return x<v?0:1;
        }
    };
    
    void rotate(Node *&o,int d)       //节点o旋转,方向d={0(左旋);1(右旋)},o的(d^1)方向的儿子k成为父节点,o成为其d方向的儿子,而原k的d方向的儿子成为o的(d^1)方向的儿子(注:(d^1)方向为d的相反方向)
    {
        Node *k=o->ch[d^1];
        o->ch[d^1]=k->ch[d];
        k->ch[d]=o;
        o=k;
    
    }
    void insert(Node *&o,int v,int info)      //将名为info、优先级为v的客户插入树堆o
    {
        if(o==NULL)o=new Node(v,info);        //若找到插入位置,则客户作为叶节点插入
        else{
            int d=v<o->v?0:1;                //若v小于o节点的优先级,则在o的左方向插入;否则在o的右方向插入
            insert(o->ch[d],v,info);         //该客户插入o的d方向子树
            if(o->ch[d]->r>o->r)             //若o节点的优先级小于d方向儿子的优先级,则向(d^1)方向旋转
            rotate(o,d^1);
        }
    }
    void remove(Node *&o,int v)              //在以o为根的树堆中,删除优先级为v的节点
    {
        int d=o->cmp(v);                     //o的优先级与v比较
        if(d==-1)                            //若o与v的优先级相同
        {
            Node *u=o;                       //记下原子根
            if(o->ch[0]&&o->ch[1])           //若o有左右子树,则计算被删节点的方向,d2={0(左儿子优先级小,被删节点在左子树方向);1(否则,被删节点在右子树方向)}
            {
                int d2=o->ch[0]->r<o->ch[1]->r?0:1;
                rotate(o,d2);                //o向d2方向旋转
                remove(o->ch[d2],v);         //在o的d2方向的子树中递归搜索
            }
            else                             //若o节点仅有一个孩子,则将其孩子节点取代o
            {
                if(o->ch[0]==NULL)o=o->ch[1];
                else o=o->ch[0];
                delete u;                    //删除原子根
            }
        }
        else remove(o->ch[d],v);             //否则o节点为叶节点,直接将其删除
    
    }
    
    int find_max(Node *o)                    //在以o为根的子树堆中寻找最大的优先值
    {
        if(o->ch[1]==NULL)                   //若o的右子树为空,则o的优先级最大,输出o的客户编号,并返回o的客户优先级           
        {
            printf("%d\n",o->info);
            return o->v;
        }
        return find_max(o->ch[1]);           //否则沿o的右子树方向继续寻找
    
    }
    int find_min(Node *o)                   //在以o为根的子树堆中寻找最小的优先值
    {
        if(o->ch[0]==NULL)                  //若o的左子树为空,则o的优先级最小,输出o的客户编号,并返回o的客户优先级
        {
            printf("%d\n",o->info);
            return o->v;
        }
        return find_min(o->ch[0]);         //否则沿o的左子树方向继续寻找
    }
    int main()
    {
        int op;
        Node *root=NULL;
        while(scanf("%d",&op)==1&&op)      //反复输入代码op,直至输入0为止
        {
            if(op==1)                      //若需要加入新客户,则输入客户名info和客户优先级v
            {
                int info,v;
                scanf("%d%d",&info,&v);
                insert(root,v,info);       //将该客户插入以root为根的树堆
            }
            else if(op==2)                 //若需删除最高优先级的客户
            {
                if(root==NULL){printf("0\n");continue;} //若树堆为空,则继续输入下一个请求
                int v=find_max(root);      //从树堆中找出最高优先级v
                remove(root,v);            //删除优先级为v的节点
            }
            else if(op==3)                 //若需删除最低优先级的客户
            {
                if(root==NULL){printf("0\n");continue;} //若树堆为空,则继续输入下一个请求
                int v=find_min(root);      //从树堆中找出最低优先级v
                remove(root,v);            //删除优先级为v的节点
            }
        }
    }

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值