[Daily]猫狗队列——”子类管理器“

【题目】

  • 有猫狗类如下:
class Pet
{
    private:
        string m_type;

    public:
        Pet(string _type){ m_type=_type; }
        string GetPetType(){ return m_type; }
};

class Dog : public Pet
{
    public:
        Dog() : Pet("dog"){}
};

class Cat : public Pet
{
    public:
        Cat() : Pet("cat"){}
};
  • 要求实现如下功能:

    • add:方法将cat类或dog类的实例放入队列
    • pollAll : 将队列出队(按照队列的先后顺序)
    • pollDog:将队列的dog类实例按照队列的先后顺序出队
    • pollCat:同理
    • isEmpty:队列是否为空
    • isDogEmpty:检查队列是否存在dog类实例
    • isCatEmpty:同理

【分析】

  • 猫和狗两个类皆为Pet类的子类。很显然,最适合的方法就是利用两个队列来组合在同一个类里面。那么问题来了,如何在两个队列中确定总的入队顺序呢?
  • 确定总入队顺序主要是为了满足 pollAll 方法的实现。
  • 在书中明确指出了最好不要改变原本的猫狗类,因此我们可以将这两个类做一层包装。而数据类型用Pet来表示Cat 和 Dog,Pet作为统一的数据类型。
  • 设计一个Tag时间戳来记录入队顺序即可

这里有一个问题:既然已经猫和狗既然被封装成同一个类型,为什么不直接用一个队列存储即可?
因为我们还要考虑到上述7种操作种,4种分别对类进行操作,如果只用以一个队列进行存储,复杂度将会大大提高。
这是很显然的,具体问题具体分析,本题考察的就是特殊数据结构的设计

【实现】

  • 实现语言:C++
  • 源代码
/*猫狗队列*/

#include<iostream>
#include<string>
#include<queue>
using namespace std;

class Pet
{
    private:
        string m_type;

    public:
        Pet(){}
        Pet(string _type){ m_type=_type; }
        string GetPetType(){ return m_type; }
};

class Dog : public Pet
{
    public:
        Dog() : Pet("dog"){}
};

class Cat : public Pet
{
    public:
        Cat() : Pet("cat"){}
};

//将两个同父类的子类(Cat And Dog)包装起来
//方便用同种泛型的Queue包装起来
class PetEnterQueue
{
    private:
        Pet m_pet;
        long m_count;    //这个类的最终目的:就是包装一个时间戳,以确定入队的顺序 

    public:
        PetEnterQueue(Pet _pet,long _count)
        {
            m_pet=_pet;
            m_count=_count;
        }

        Pet getPet() { return m_pet;}
        long getCount(){ return m_count;}
        string getType(){ return m_pet.GetPetType();}
}; 

//猫狗队列类
class CatAndDogQueue
{
    private:
        queue<PetEnterQueue> m_catQueue;  //猫队列
        queue<PetEnterQueue> m_dogQueue;  //狗队列
        long m_Count;                     //队列元素的个数

    public:
        CatAndDogQueue(){ m_Count=0; }    //构造函数中将容量设为0

        //主要操作函数

        //add:方法将cat类或dog类的实例放入队列
        void add(Pet pet)
        {
            if(pet.GetPetType()=="dog") //狗元素
                m_dogQueue.push(PetEnterQueue(pet,m_Count++));
            else if(pet.GetPetType()=="cat")
                m_catQueue.push(PetEnterQueue(pet,m_Count++));
            else
                cout<<"添加的元素类型有误,请检查!"<<endl;
        } 

        //pollAll : 将队列出队(按照队列的先后顺序)
        Pet pollAll()
        {
            Pet pet;
            if(!m_catQueue.empty()&&!m_dogQueue.empty())    //两个队列皆不为空时
            {
                if(m_catQueue.front().getCount() > m_dogQueue.front().getCount())
                {
                    pet=m_dogQueue.front().getPet();
                    m_dogQueue.pop();
                }
                else
                {
                    pet=m_catQueue.front().getPet();
                    m_catQueue.pop();
                }
            }
            else if(!m_dogQueue.empty())
            {
                pet=m_dogQueue.front().getPet();
                m_dogQueue.pop();
            }
            else if(!m_catQueue.empty())
            {
                pet=m_catQueue.front().getPet();
                m_catQueue.pop();
            }
            else
            {
                cout<<"当前队列为空队,无法出队!"<<endl;
                return pet;
            }

            return pet;
        }

        //pollDog:将队列的dog类实例按照队列的先后顺序出队
        Pet pollDog()
        {
            Pet pet;
            if(m_dogQueue.empty())
            {
                cout<<"狗队为空,无法出队"<<endl;
                return pet;
            }
            pet=m_dogQueue.front().getPet();
            m_dogQueue.pop();
            return pet;
        } 

        //pollCat:同理
        Pet pollCat()
        {
            Pet pet;
            if(m_catQueue.empty())
            {
                cout<<"猫队为空,无法出队"<<endl;
            }
            pet=m_catQueue.front().getPet();
            m_catQueue.pop();
            return pet;
        }

        //isEmpty:队列是否为空
        bool isEmpty()
        {
            return m_dogQueue.empty()&&m_catQueue.empty();
        } 

        //isDogEmpty:检查队列是否存在dog类实例
        bool isDogEmpty()
        {
            return m_dogQueue.empty();
        }

        //isCatEmpty:同理
        bool isCatEmpty()
        {
            return m_catQueue.empty();
        }   

        void ShowCount()
        {
            cout<<"dog count : "<<m_dogQueue.size()<<endl;
            cout<<"cat count : "<<m_catQueue.size()<<endl;
            //cout<<"合计      : "<< m_dogQueue.size()+m_catQueue.size()<<endl;
        }
}; 

【此外】

  • "子类管理器",顾名思义,它可以很好的管理同一个父类的不同子类的集合。这可以延申到其他数据结构中
  • 在C++中,子类实例转化为父类实例(在我印象中,这是没有的,也是不提倡的)。而Java上可以强制类型转换。因此,在pollCat()等方法中也可以返回子类类型,上述C++我直接返回Pet(父类类型)
  • 可以直接父类实例给子类实例进行赋值(在编写代码时没有想到这一点)
Pet pet;
Dog dog;
Pet *pPet=&dog;
*pPet=pet;     //赋值成功

原文地址:https://www.cnblogs.com/ZhuSenlin/p/12388326.html

时间: 2024-08-11 22:09:57

[Daily]猫狗队列——”子类管理器“的相关文章

猫狗队列

1,add方法将Dog实例或Cat实例加入猫狗队列 2,pollAll将猫狗队列中的实例按插入顺序弹出 3,pollDog将猫狗队列中的Dog实例按插入顺序弹出 4,pollCat将猫狗队列中的Cat实例按插入顺序弹出 5,isEmpty判断猫狗队列中是否还有实例 6,isDogEmpty判断猫狗队列中是否还有Dog实例 7,isCatEmpty判断猫狗队列中是否还有Cat实例 #!/usr/bin/env python3 # --*-- coding: utf-8 --*-- from col

6.猫狗队列问题

问题:宠物.狗.猫的类如下 class Pet { private String type; public Pet(String type) { this.type = type; } public String getType() { return this.type; } public String toString(){ return this.getType(); } } class Dog extends Pet { public Dog(String type) { super(ty

用STL设计消息队列、优先级消息队列、资源分配管理器

STL库老早已经成为C++的一部分,在使用C++开发项目的过程中,很多人还在犹豫要不要使用STL库,觉得STL库很难,其实不然.我工作的项目中现在大量使用STL库,STL使用调试简单,高效,可以减少很多重复的代码. 本文的主要目的是使用STL的queue 和 priority queue来阐述下项目中经常使用的消息队列以及资源分配模式.本文的例子主要如下: 消息队列 带优先级的消息队列 资源分配管理器 STL容器 我们将使用下面的容器来实现本文的例子: queue 队列容器支持添加一个元素,并且

MQ队列管理器搭建(一)

多应用单MQ使用场景 如上图所示,MQ独立安装,或者与其中一个应用同处一机.Application1与Application2要进行通信,但因为跨系统,所以引入中间件来实现需求. Application1需要连接MQ,并将消息放入队列Queue中,Application2同样连接MQ,监听在Queue队列上,一旦发现有消息进入则取出该消息进行处理. 下面将给出创建队列管理器和队列的示例: 定义队列管理器名称为Qm1,本地队列名称为Queue,服务器连接通道CHAN_SERVER_CON,监听端口

MQ队列管理器搭建(三)

MQ集群及网关队列管理器的搭建 描述: 如上图所示,为MQ的集群搭建部署图.CLUSTERA.CLUSTERB分别是两个集群,其中Qm1-Qm3.GateWayA为CLUSTERA集群中的队列管理器:Qm1-Qm3.GateWayB是CLUSTERB集群中的队列管理器.GateWayA与GateWayB负责网络路由和消息分发,使用集群的方式可以达到负载均衡的目的,除此之外还能提高MQ使用的稳定性.同一个集群中除网关队列管理器外的任意队列管理器因故关闭或停止工作后,其他的队列管理器可以接管它的工作

MQ队列管理器搭建(二)

MQ级联方式使用场景 使用场景: 如上图所示,Application1与Application2要进行通信或者消息互换,使用MQ中间件作为中介.上图中,Application1与Application2通信不进行直接连接,而是通过与MQ通信从而实现二者的通信.图中两个MQ的信息如上描述.其中RemoteQueue为远程队列,该队列指定了目标端对应的队列为Queue,并且该远程队列指定了传输所使用的传输队列尾TransQueue:而此传输队列TransQueue与发送通道CHAN_QMGR1_TO

JMSWMQ0018: 连接至队列管理器 &#39;QMGR&#39; 失败,连接方式为 &#39;Bindings&#39;

之前写的一个用JMS监听MQ的java程序,调用本地MQ一起正常.可是今天突然去调用远程服务器上的队列时却报错了. 以下是报错信息 Exception in thread "main" org.springframework.jms.UncategorizedJmsException: Uncategorized exception occured during JMS processing; nested exception is com.ibm.msg.client.jms.Det

QT开发(二十一)——QT布局管理器

QT开发(二十一)--QT布局管理器 一.布局管理器简介 QT中使用绝对定位的布局方式无法自适应窗口的变化. QT中提供了对界面组件进行布局管理的类,用于对界面组件进行管理,能够自动排列窗口中的界面组件,窗口大小变化后自动更新界面组件的大小. QLayout是QT中布局管理器的抽象基类,通过对QLayout的继承,实现了功能各异且互补的布局管理器. 布局管理器不是界面组件,而是界面组件的定位策略. 任意容器类型的组件都可以指定布局管理器. 同一个布局管理器管理中的组件拥有相同的父组件,在设置布局

Linux新手的最佳包管理器

一个 Linux 新用户应该知道他或她的进步源自于对 Linux 发行版的使用,而 Linux 发行版有好几种,并以不同的方式管理软件包. 在 Linux开发 中,包管理器非常重要,知道如何使用多种包管理器可以让你像一个高手一样活得很舒适,从在仓库下载软件.安装软件,到更新软件.处理依赖和删除软件是非常重要的,这也是Linux 系统管理的一个重要部分. 成为一个 Linux 高手的一个标志是了解主要的 Linux 发行版如何处理包,在这篇文章中,我们应该看一些你在 Linux 上能找到的最佳的包