猫狗队列

守給你的承諾、 提交于 2020-03-07 10:58:36

【说明】:

  本文是左程云老师所著的《程序员面试代码指南》第一章中“猫狗队列”这一题目的C++复现。

  本文只包含问题描述、C++代码的实现以及简单的思路,不包含解析说明,具体的问题解析请参考原书。

  感谢左程云老师的支持。

【题目】:

  宠物、狗和猫的类如下:

/*
 *文件名:pet.h
 *作者:
 *摘要:pet、cat、dog的原声明及实现
 */
#ifndef _PET_H
#define _PET_H

#include <string>

using namespace std;

class Pet
{
public:
    Pet(string type)
    {
        this->type = type;
    }
    string getPetType()
    {
        return type;
    }
private:
    string type;
};

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

class Cat:public Pet
{
public:
    Cat():Pet("cat"){}
};
#endif
View Code

  实现一种猫狗队列的结构,要求如下:

  • 用户可以调用 push 的方法,将 cat 类或者 dog 类的实例放入队列中;
  • 用户可以调用 popAll 的方法,将队列中所有的实例按照进队列的先后顺序依次弹出;
  • 用户可以调用 popDog 的方法,将队列中的 dog 类实例按照进队列的先后顺序依次弹出;
  • 用户可以调用 popCat 的方法,将队列中的 cat 类实例按照进队列的先后顺序依次弹出;
  • 用户可以调用 isEmpty 的方法,检查队列中是否还有 dog 或者 cat 类的实例;
  • 用户可以调用 isDogEmpty 的方法,检查队列中是否还有 dog 类的实例;
  • 用户可以调用 isCatEmpty 的方法,检查队列中是否还有 cat 类的实例。

【思路】:

  以时间戳的方法区分猫狗的进入顺序。

【编译环境】:

  CentOS6.7(x86_64)

  gcc 4.4.7

【实现】:

  1、带时间戳的宠物类声明及实现代码

/*
 *文件名:petstamp.h
 *作者:
 *摘要:为添加的pet创建时间戳
 */
#ifndef _PETSTAMP_H
#define _PETSTAMP_H

#include "pet.h"

class PetStamp
{
public:
    PetStamp(Pet p,long count)
    :pet(p)
    {
        this->count = count;
    }
    Pet getPet()
    {
        return pet;
    }
    long getCount()
    {
        return count;
    }
    string getPetType()
    {
        return pet.getPetType();
    }
private:
    Pet pet;
    long count;
};
#endif
View Code

  2、猫狗队列的声明代码

/*
 *文件名:CatDogQue.h
 *作者:
 *摘要:猫狗队列的声明
 */
#ifndef _CATDOGQUE_H
#define _CATDOGQUE_H

#include "pet.h"
#include "petstamp.h"
#include <queue>

using namespace std;

class CatDogQue
{
public:
    CatDogQue();
    void push(Pet pet);    
    Pet popAll();
    Dog popDog();
    Cat popCat();
    bool isEmpty();
    bool isDogEmpty();
    bool isCatEmpty();
private:
    queue<PetStamp> dogQ;
    queue<PetStamp> catQ;
    long count;
};
#endif
View Code

  3、猫狗队列的实现代码

/*
 *文件名:CatDogQue.cpp
 *作者:
 *摘要:猫狗队列的声明。
 */
#include "CatDogQue.h"
#include <stdexcept>

using namespace std;

CatDogQue::CatDogQue()
{
    count = 0;
}

void CatDogQue::push(Pet pet)
{
    if("dog" == pet.getPetType())
        dogQ.push(PetStamp(pet,count++));
    else if("cat" == pet.getPetType())
        catQ.push(PetStamp(pet,count++));
    else
        throw runtime_error("err,not dog or cat!");
    return ;
}

Pet CatDogQue::popAll()
{
    if(!catQ.empty() && !dogQ.empty())
    {
        if(dogQ.front().getCount() < catQ.front().getCount())
        {
            Pet tmp = dogQ.front().getPet();
            dogQ.pop();
            return tmp;
        }
        else
        {
            Pet tmp = catQ.front().getPet();
            catQ.pop();
            return tmp;
        }
    }
    else if (!catQ.empty())
    {
        Pet tmp = catQ.front().getPet();
        catQ.pop();
        return tmp;
    }
    else if (!dogQ.empty())
    {
        Pet tmp = dogQ.front().getPet();
        dogQ.pop();
        return tmp;
    }
    else 
    {
        throw runtime_error("Error,empty queue!");
    }
}


Dog CatDogQue::popDog()
{
    if (!dogQ.empty())
    {
        Pet tmpP = dogQ.front().getPet();
        Dog tmpD;
        Pet *pd = &tmpD;
        *pd = tmpP;
        
        dogQ.pop();
        return tmpD;
    }
    else 
    {
        throw runtime_error("Error,empty dog queue!");
    }
}


Cat CatDogQue::popCat()
{
    if (!catQ.empty())
    {
        Pet tmpP = catQ.front().getPet();
        Cat tmpC;
        Pet *pc = &tmpC;
        *pc = tmpP;
        
        catQ.pop();
        return tmpC;
    }
    else 
    {
        throw runtime_error("Error,empty cat queue!");
    }
}

bool CatDogQue::isEmpty()
{
    return dogQ.empty() && catQ.empty();
}


bool CatDogQue::isDogEmpty()
{
    return dogQ.empty();
}

bool CatDogQue::isCatEmpty()
{
    return catQ.empty();
}
View Code

  4、测试代码

/*
 *文件名:test.cpp
 *作者:
 *摘要:猫狗队列的测试代码
 */

#include "CatDogQue.h"
#include <iostream>

using namespace std;

int main()
{
    CatDogQue cdq;
    if(cdq.isEmpty())
        cout << "All queue is empty!" << endl;
    cdq.push(Dog());
    if(!cdq.isDogEmpty())
        cout << "Dog queue is not empty!" << endl;
    if(cdq.isCatEmpty())
        cout << "Cat queue is Empty!" << endl;
    for(int i=0;i<2;i++)
    {
        cdq.push(Cat());
        cdq.push(Dog());
    }
    cout << "popAll:" << cdq.popAll().getPetType() << endl;
    cout << "popDog:" << cdq.popDog().getPetType() << endl;
    cout << "popCat:" << cdq.popCat().getPetType() << endl;    
    cout << "popAll:" << cdq.popAll().getPetType() << endl;
    cout << "popAll:" << cdq.popAll().getPetType() << endl;
    if(cdq.isEmpty())
        cout << "All queue is empty!" << endl;

    return 0;
}
View Code

【一点说明】

  1、子类对象可以直接给父类赋值

  2、父类对象不可以直接给子类对象赋值

  3、解决父类对象不可以直接给子类对象赋值的问题的小技巧:    

class A
{};
class B:public A        //B继承于A
{};

A a;    
B b;
A *pa = &b;  //声明类型为A的指针pa,并将子类对象b的地址赋予pa
*pa = a;    //实现了父类对子类的赋值
View Code

 

注:

  转载请注明出处;

  转载请注明源思路来自于左程云老师的《程序员代码面试指南》。

【说明】:

  本文是左程云老师所著的《程序员面试代码指南》第一章中“猫狗队列”这一题目的C++复现。

  本文只包含问题描述、C++代码的实现以及简单的思路,不包含解析说明,具体的问题解析请参考原书。

  感谢左程云老师的支持。

【题目】:

  宠物、狗和猫的类如下:

/*
 *文件名:pet.h
 *作者:
 *摘要:pet、cat、dog的原声明及实现
 */
#ifndef _PET_H
#define _PET_H

#include <string>

using namespace std;

class Pet
{
public:
    Pet(string type)
    {
        this->type = type;
    }
    string getPetType()
    {
        return type;
    }
private:
    string type;
};

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

class Cat:public Pet
{
public:
    Cat():Pet("cat"){}
};
#endif
View Code

  实现一种猫狗队列的结构,要求如下:

  • 用户可以调用 push 的方法,将 cat 类或者 dog 类的实例放入队列中;
  • 用户可以调用 popAll 的方法,将队列中所有的实例按照进队列的先后顺序依次弹出;
  • 用户可以调用 popDog 的方法,将队列中的 dog 类实例按照进队列的先后顺序依次弹出;
  • 用户可以调用 popCat 的方法,将队列中的 cat 类实例按照进队列的先后顺序依次弹出;
  • 用户可以调用 isEmpty 的方法,检查队列中是否还有 dog 或者 cat 类的实例;
  • 用户可以调用 isDogEmpty 的方法,检查队列中是否还有 dog 类的实例;
  • 用户可以调用 isCatEmpty 的方法,检查队列中是否还有 cat 类的实例。

【思路】:

  以时间戳的方法区分猫狗的进入顺序。

【编译环境】:

  CentOS6.7(x86_64)

  gcc 4.4.7

【实现】:

  1、带时间戳的宠物类声明及实现代码

/*
 *文件名:petstamp.h
 *作者:
 *摘要:为添加的pet创建时间戳
 */
#ifndef _PETSTAMP_H
#define _PETSTAMP_H

#include "pet.h"

class PetStamp
{
public:
    PetStamp(Pet p,long count)
    :pet(p)
    {
        this->count = count;
    }
    Pet getPet()
    {
        return pet;
    }
    long getCount()
    {
        return count;
    }
    string getPetType()
    {
        return pet.getPetType();
    }
private:
    Pet pet;
    long count;
};
#endif
View Code

  2、猫狗队列的声明代码

/*
 *文件名:CatDogQue.h
 *作者:
 *摘要:猫狗队列的声明
 */
#ifndef _CATDOGQUE_H
#define _CATDOGQUE_H

#include "pet.h"
#include "petstamp.h"
#include <queue>

using namespace std;

class CatDogQue
{
public:
    CatDogQue();
    void push(Pet pet);    
    Pet popAll();
    Dog popDog();
    Cat popCat();
    bool isEmpty();
    bool isDogEmpty();
    bool isCatEmpty();
private:
    queue<PetStamp> dogQ;
    queue<PetStamp> catQ;
    long count;
};
#endif
View Code

  3、猫狗队列的实现代码

/*
 *文件名:CatDogQue.cpp
 *作者:
 *摘要:猫狗队列的声明。
 */
#include "CatDogQue.h"
#include <stdexcept>

using namespace std;

CatDogQue::CatDogQue()
{
    count = 0;
}

void CatDogQue::push(Pet pet)
{
    if("dog" == pet.getPetType())
        dogQ.push(PetStamp(pet,count++));
    else if("cat" == pet.getPetType())
        catQ.push(PetStamp(pet,count++));
    else
        throw runtime_error("err,not dog or cat!");
    return ;
}

Pet CatDogQue::popAll()
{
    if(!catQ.empty() && !dogQ.empty())
    {
        if(dogQ.front().getCount() < catQ.front().getCount())
        {
            Pet tmp = dogQ.front().getPet();
            dogQ.pop();
            return tmp;
        }
        else
        {
            Pet tmp = catQ.front().getPet();
            catQ.pop();
            return tmp;
        }
    }
    else if (!catQ.empty())
    {
        Pet tmp = catQ.front().getPet();
        catQ.pop();
        return tmp;
    }
    else if (!dogQ.empty())
    {
        Pet tmp = dogQ.front().getPet();
        dogQ.pop();
        return tmp;
    }
    else 
    {
        throw runtime_error("Error,empty queue!");
    }
}


Dog CatDogQue::popDog()
{
    if (!dogQ.empty())
    {
        Pet tmpP = dogQ.front().getPet();
        Dog tmpD;
        Pet *pd = &tmpD;
        *pd = tmpP;
        
        dogQ.pop();
        return tmpD;
    }
    else 
    {
        throw runtime_error("Error,empty dog queue!");
    }
}


Cat CatDogQue::popCat()
{
    if (!catQ.empty())
    {
        Pet tmpP = catQ.front().getPet();
        Cat tmpC;
        Pet *pc = &tmpC;
        *pc = tmpP;
        
        catQ.pop();
        return tmpC;
    }
    else 
    {
        throw runtime_error("Error,empty cat queue!");
    }
}

bool CatDogQue::isEmpty()
{
    return dogQ.empty() && catQ.empty();
}


bool CatDogQue::isDogEmpty()
{
    return dogQ.empty();
}

bool CatDogQue::isCatEmpty()
{
    return catQ.empty();
}
View Code

  4、测试代码

/*
 *文件名:test.cpp
 *作者:
 *摘要:猫狗队列的测试代码
 */

#include "CatDogQue.h"
#include <iostream>

using namespace std;

int main()
{
    CatDogQue cdq;
    if(cdq.isEmpty())
        cout << "All queue is empty!" << endl;
    cdq.push(Dog());
    if(!cdq.isDogEmpty())
        cout << "Dog queue is not empty!" << endl;
    if(cdq.isCatEmpty())
        cout << "Cat queue is Empty!" << endl;
    for(int i=0;i<2;i++)
    {
        cdq.push(Cat());
        cdq.push(Dog());
    }
    cout << "popAll:" << cdq.popAll().getPetType() << endl;
    cout << "popDog:" << cdq.popDog().getPetType() << endl;
    cout << "popCat:" << cdq.popCat().getPetType() << endl;    
    cout << "popAll:" << cdq.popAll().getPetType() << endl;
    cout << "popAll:" << cdq.popAll().getPetType() << endl;
    if(cdq.isEmpty())
        cout << "All queue is empty!" << endl;

    return 0;
}
View Code

【一点说明】

  1、子类对象可以直接给父类赋值

  2、父类对象不可以直接给子类对象赋值

  3、解决父类对象不可以直接给子类对象赋值的问题的小技巧:    

class A
{};
class B:public A        //B继承于A
{};

A a;    
B b;
A *pa = &b;  //声明类型为A的指针pa,并将子类对象b的地址赋予pa
*pa = a;    //实现了父类对子类的赋值
View Code

 

注:

  转载请注明出处;

  转载请注明源思路来自于左程云老师的《程序员代码面试指南》。

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!