1. 题目:
有家动物收容所只收容狗与猫,且严格遵守“先进先出”的原则。在收养该收容所的动物时,收养人只能收养所有动物中“最老”(由其进入收容所的时间长短而定)的动物,或者可以挑选猫或狗(同时必须收养此类动物中“最老”的)。换言之,收养人不能自由挑选想收养的对象。请创建适用于这个系统的数据结构,实现各种操作方法,比如 enqueue、dequeueAny、dequeueDog 和 dequeueCat。
2. 解题思路:
使用两个独立的队列分别存储狗和猫。
每个动物进入时都会记录精确的时间戳。
图解下面代码的整个过程:
1.初始状态
动物收容所:
狗队列: []
猫队列: []
2.收容动物流程 (enqueue)
1. 收容Buddy(狗)
狗队列: [Buddy(ts=1)]
猫队列: []
2. 收容Fluffy(猫)
狗队列: [Buddy(ts=1)]
猫队列: [Fluffy(ts=2)]
3. 收容Max(狗)
狗队列: [Buddy(ts=1), Max(ts=3)]
猫队列: [Fluffy(ts=2)]
4. 收容Mittens(猫)
狗队列: [Buddy(ts=1), Max(ts=3)]
猫队列: [Fluffy(ts=2), Mittens(ts=4)]
3.收养流程 (dequeue)
1. dequeueAny():
比较Buddy(ts=1)和Fluffy(ts=2)
选择Buddy(最早)
狗队列: [Max(ts=3)]
猫队列: [Fluffy(ts=2), Mittens(ts=4)]
2. dequeueCat():
选择Fluffy(猫队列最早)
狗队列: [Max(ts=3)]
猫队列: [Mittens(ts=4)]
3. dequeueDog():
选择Max(狗队列最早)
狗队列: []
猫队列: [Mittens(ts=4)]
3. 代码完整实现(C++):
#include <chrono>
#include <iostream>
#include <queue>
#include <string>
#include <thread>
class Animal {
protected:
std::string name;
int64_t orderTs; // 用于记录动物进入收容所的时间(unix毫秒)
public:
Animal(const std::string& n) : name(n) {}
virtual ~Animal() = default;
void setOrderTs(int64_t ts) { orderTs = ts; }
int64_t getOrderTs() { return orderTs; }
std::string getName() const { return name; }
// 重载<运算符,用于优先队列比较
bool operator<(const Animal& other) const {
// 较小的order表示更早进入
return this->orderTs < other.orderTs;
}
};
class Dog : public Animal {
public:
Dog(const std::string& n) : Animal(n) {}
};
class Cat : public Animal {
public:
Cat(const std::string& n) : Animal(n) {}
};
class AnimalShelter {
private:
std::queue<std::unique_ptr<Dog>> dogs;
std::queue<std::unique_ptr<Cat>> cats;
public:
AnimalShelter() {}
// 收容动物
void enqueue(std::unique_ptr<Animal> animal) {
// 获取当前时间点
auto now = std::chrono::system_clock::now();
// 计算unix时间戳的毫秒数
int64_t nowTs = std::chrono::duration_cast<std::chrono::milliseconds>(
now.time_since_epoch())
.count();
animal->setOrderTs(nowTs);
if (dynamic_cast<Dog*>(animal.get())) {
// 转移所有权到dogs队列
dogs.push(
std::unique_ptr<Dog>(static_cast<Dog*>(animal.release())));
} else if (dynamic_cast<Cat*>(animal.get())) {
cats.push(
std::unique_ptr<Cat>(static_cast<Cat*>(animal.release())));
}
}
// 收养所有动物中最老的
std::unique_ptr<Animal> dequeueAny() {
if (dogs.empty() && cats.empty()) {
return nullptr;
} else if (dogs.empty()) {
return dequeueCat();
} else if (cats.empty()) {
return dequeueDog();
}
Dog* dog = dogs.front().get();
Cat* cat = cats.front().get();
if (*dog < *cat) {
return dequeueDog();
} else {
return dequeueCat();
}
}
// 收养最老的狗
std::unique_ptr<Dog> dequeueDog() {
if (dogs.empty()) {
return nullptr;
}
auto dog = std::move(dogs.front());
dogs.pop();
return dog;
}
// 收养最老的猫
std::unique_ptr<Cat> dequeueCat() {
if (cats.empty()) {
return nullptr;
}
auto cat = std::move(cats.front());
cats.pop();
return cat;
}
};
int main() {
AnimalShelter shelter;
// 收容动物
shelter.enqueue(std::make_unique<Dog>("Buddy"));
std::this_thread::sleep_for(std::chrono::milliseconds(5));
shelter.enqueue(std::make_unique<Cat>("Fluffy"));
std::this_thread::sleep_for(std::chrono::milliseconds(5));
shelter.enqueue(std::make_unique<Dog>("Max"));
std::this_thread::sleep_for(std::chrono::milliseconds(5));
shelter.enqueue(std::make_unique<Cat>("Mittens"));
// 收养最老的动物(应该是Buddy)
auto a = shelter.dequeueAny();
if (a)
std::cout << "收养了: " << a->getName() << std::endl;
// 收养最老的猫(应该是Fluffy)
auto c = shelter.dequeueCat();
if (c)
std::cout << "收养了猫: " << c->getName() << std::endl;
// 收养最老的狗(应该是Max)
auto d = shelter.dequeueDog();
if (d)
std::cout << "收养了狗: " << d->getName() << std::endl;
return 0;
}
4. 代码分析:
这个实现严格遵循了题目要求:
- 只使用队列结构
- 支持按类型或全部收养
- 保证总是收养最老的动物
- 使用智能指针避免内存泄漏
时间复杂度:
enqueue: O(1)
dequeueAny: O(1)
dequeueDog/dequeueCat: O(1)
空间复杂度:
O(n),需要存储所有动物
5. 运行结果:
养了: Buddy
收养了猫: Fluffy
收养了狗: Max
感谢您的阅读。原创不易,如您觉得有价值,请点赞,关注。