猫狗队列(c++)
【说明】:
本文是左程云老师所著的《程序员面试代码指南》第一章中“猫狗队列”这一题目的C++复现。
本文只包含问题描述、C++代码的实现以及简单的思路,不包含解析说明,具体的问题解析请参考原书。
感谢左程云老师的支持。
#include <iostream>
#include <string>
#include<queue>
#include<stdexcept>//标准异常库
using namespace std;
//猫狗队列
//在C++中,类是不能加权限修饰符的,只有类的成员或者继承的时候才能加。
//这里是public继承,意思是Pet中所有的访问权限在Dog中不变,如果是peivate继承,那么是说Pet中的所有成员变成Dog的私有成员。
//在子类的构造函数中调用父类的有参构造函数就是下面这么用Cat():Pet("Cat"){};
class Pet
{
private:
string type;
public:
Pet(string type)
{
this->type = type;
}
Pet() {}
string getPetType()
{
return this->type;
}
};
class Dog :public Pet
{
public :
Dog():Pet("dog") {}
};
class Cat :public Pet
{
public:
Cat() :Pet("cat") {}
};
/************************以上为题目给出原始接口***********************/
//使用一个带时间戳的Pet类区分猫狗的进入顺序
class PetTimeStamp
{
private:
Pet mypet;
long timestamp;
public:
//构造函数后面加了:是初始化列表,初始化myPet为p
PetTimeStamp(Pet p, long count) :mypet(p)
{
this->timestamp = count;
}
Pet getPet()
{
return mypet;
}
long getTimeStamp()
{
return timestamp;
}
string getPetType()
{
return mypet.getPetType();
}
};
//猫狗队列类,这列面有两个队列,每个队列的元素是加了时间戳的Pet类
class CatDogQ
{
private:
queue<PetTimeStamp> dogQ, catQ;
long timestamp;
public:
CatDogQ()
{
timestamp = 0;
}
void push(Pet pet);
Pet popAll();
Dog popDog();
Cat popCat();
bool isEmpty();
bool DogisEmpty();
bool CatisEmpty();
};
//猫狗入队,入队的同时打上时间戳
void CatDogQ::push(Pet pet)
{
if (pet.getPetType() == "dog")
dogQ.push(PetTimeStamp(pet, this->timestamp++));
else if (pet.getPetType() == "cat")
catQ.push(PetTimeStamp(pet, this->timestamp++));
else
throw runtime_error("err, not dog or cat!");
}
由于是两个队列,因此要按照时间戳弹出,区分三种情况 :1 猫狗都有、2只有猫、3只有狗、都没有
Pet CatDogQ::popAll()
{
if (!dogQ.empty() && !catQ.empty())//如果二者都不为空,按照时间错大小依次弹出
{
if (dogQ.front().getTimeStamp() < catQ.front().getTimeStamp())
{
Pet tmp;
tmp = dogQ.front().getPet();
dogQ.pop();
return tmp;
}
else
{
Pet tmp;
tmp = catQ.front().getPet();
catQ.pop();
return tmp;
}
}
else if (!dogQ.empty())
{
Pet tmp;
tmp = dogQ.front().getPet();
dogQ.pop();
return tmp;
}
else if (!catQ.empty())
{
Pet tmp;
tmp = catQ.front().getPet();
catQ.pop();
return tmp;
}
else
{
throw runtime_error("Error ,empty queue!");
}
}
Dog CatDogQ::popDog()
{
if (!DogisEmpty())
{
Pet temP = dogQ.front().getPet();
Dog tmp;
Pet *p = &tmp;
*p = temP;
dogQ.pop();
return tmp;
}
else
throw runtime_error("Error,empty dog queue!");
}
Cat CatDogQ::popCat()
{
if (!CatisEmpty())
{
Pet temP = catQ.front().getPet();
Cat tmp;
Pet *p = &tmp;
*p = temP;
catQ.pop();
return tmp;
}
else
throw runtime_error("Error,empty cat queue!");
}
bool CatDogQ::isEmpty()
{
return catQ.empty() && dogQ.empty();
}
bool CatDogQ::DogisEmpty()
{
return dogQ.empty();
}
bool CatDogQ::CatisEmpty()
{
return catQ.empty();
}
int main()
{
CatDogQ cdq;
if (cdq.isEmpty())
cout << "All queue is empty!" << endl;
cdq.push(Cat());
if (!cdq.DogisEmpty())
cout << "Dog queue is not empty!" << endl;
if (!cdq.CatisEmpty())
cout << "Cat queue is not empty!" << endl;
for (int i = 0; i < 2; i++)
{
cdq.push(Dog());
cdq.push(Cat());
}
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;
}