概述
队列ADT我相信大家都很清楚,就是FIFO嘛。
这一篇,关键讲队列怎么实现。
实现
循环数组实现。
template<typename T>
class Queue_array
{
public:
Queue_array(int maxsize = 10) : maxsize_(maxsize),
size_(0), front_(1), rear_(0)
{
pa_ = new T[maxsize_];// 初始化数组,默认大小为10
}
virtual ~Queue_array()
{
delete[] pa_;
}
public:
void push(const T& x)
{
if (isFull())
return;
size_++;
rear_++;
rear_ %= maxsize_;// 让rear在将要越界的时候,回到0,从而实现循环
*(pa_ + rear_) = x;
}
void pop()
{
size_--;
front_++;
front_ %= 10;// 不要忘了,这里也要加
}
const T getFront()
{
return *(pa_ + front_);
}
const int getSize() const
{
return size_;
}
bool isEmpty() const
{
return size == 0;
}
bool isFull() const
{
return size_ == maxsize_;
}
private:
int front_, rear_;
T* pa_;
int size_;
int maxsize_;
};
链表实现
template<typename T>
class Queue_list {
public:
typedef struct list {
T data;
list *next;
list(T x) : data(x), next(nullptr) {}
} ListNode;
Queue_list(int maxsize = 10) : size_(0), maxsize_(maxsize) {
front_ = rear_ = new ListNode(0);// 初始化,front和rear都指向同一个结点
}
virtual ~Queue_list() {
while( front_ != rear_) {
ListNode* t = front_->next;
delete front_;
front_ = t;
}
delete rear_;
};
public:
// 插到rear现在所在的位置,并且新增一个结点让rear指向它
void push( const T& x) {
size_++;
rear_->data = x;
rear_->next = new ListNode(0);
rear_ = rear_->next;
}
// 删除front现在指向的结点,将front指向下一个结点
void pop() {
size_--;
ListNode *t = front_;
front_ = front_->next;
delete t;
}
const T getFront() {
return front_->data;
}
const int getSize() const {
return size_;
}
bool isEmpty() const {
return front == rear;
}
// 链表实现可以不考虑队列满的情况
private:
ListNode *front_, *rear_;
int size_;
int maxsize_;
};
测试用例:
int main() {
{
Queue_list<int> q;
for(auto i = 0; i<10; i++)
q.push(i);
q.pop();
assert(9 == q.getSize());
assert(1 == q.getFront());
q.push(10);
q.pop();
assert(2 == q.getFront());
}
{
Queue_array<int> q;
for(auto i = 0; i<10; i++)
q.push(i);
q.pop();
assert(9 == q.getSize());
assert(1 == q.getFront());
q.push(10);
q.pop();
assert(2 == q.getFront());
}
std::cout << "All test cases pass";
return 0;
}
应用
来学习一下STL里的deque,cppreference里对它的大概描述是:
deque(double end queue 双端队列),随机访问时间O(1),插入头和尾结点的时间是O(1),普通插入的时间是O(N)。它的存储是由多个固定大小的数组组成,而且在动态扩充大小的时候效率很高,不会像vector那样,将所有的内容重新复制到新的内存中。