1 队列也是一种退化的表,它在队尾(rear)入队(enqueue),在队首(front)出队(dequeue).和栈一样除了clear之外的所有操作都具有O(1)的时间复杂度。
2 循环队列是队列的一个特殊,队首作为队尾的后继,若是双向队列,那么队首的前驱也是队尾。
作为一种最常用的线性表,它通常用作资源缓存,因此,有必要关心队列的容量,即超出容量的情况,而其设计实现,每个程序员都有自己的一套轮子,可谓五花八门。本文介绍两种最常用实现:链表实现、数组实现。
链表实现队列
#pragma once
#include <iostream>
template<typename T_data>
struct EntryQueue
{
T_data _data;
EntryQueue() {};
EntryQueue(const T_data& data) :_data(data) {}
};
template<typename T_data>
struct NodeQueue
{
EntryQueue<T_data> _entry;
NodeQueue* _next;
NodeQueue(NodeQueue* next) :_next(next) {}
NodeQueue(const EntryQueue<T_data>& entry, NodeQueue* next) :_entry(entry), _next(next) {}
};
template<typename T_data>
class QueueByLink
{
public:
static size_t constexpr MAX_CAPACITY = 1024 * 10;
public:
QueueByLink(size_t capacity = MAX_CAPACITY);
~QueueByLink();
size_t size() { return _size; }
bool empty() { return _size == 0; }
void clear();
NodeQueue<T_data>* enqueue(const EntryQueue<T_data>& entry);
void dequeue();
NodeQueue<T_data>* front();
NodeQueue<T_data>* rear();
private:
size_t _size, _capacity;
NodeQueue<T_data>* _front, * _rear;
private:
void print();
friend void test_queuebylist();
};
void test_queuebylist()
{
QueueByLink<int> queue_link;
for (size_t i = 0; i < 129; i++)
{
EntryQueue<int> entry(i);
queue_link.enqueue(entry);
}
std::cout << "\nqueue_link size after enqueue " << queue_link.size() <<",front:"<<queue_link.front()<<",rear:"<<queue_link.rear()<< std::endl;
queue_link.print();
for (size_t i = 0; i < 129; i++)
{
queue_link.dequeue();
}
std::cout << "\nqueue_link size after dequeue " << queue_link.size() << ",front:" << queue_link.front() << ",rear:" << queue_link.rear() << std::endl;
queue_link.print();
queue_link.clear();
std::cout << "\nqueue_link size after clear " << queue_link.size() << ",front:" << queue_link.front() << ",rear:" << queue_link.rear() << std::endl;
}
template<typename T_data>
inline void QueueByLink<T_data>::clear()
{
while (_front)
{
NodeQueue<T_data>* next = _front->_next;
_front->_next = nullptr;
delete _front;
_front = next;
_size--;
}
}
template<typename T_data>
inline NodeQueue<T_data>* QueueByLink<T_data>::enqueue(const EntryQueue<T_data>& entry)
{
NodeQueue<T_data>* node;
if (_size > _capacity)
{
std::cout << "queue_by_link is full!!!\n";
return nullptr;
}
node = new NodeQueue<T_data>(entry,nullptr);
if (_rear)
{
_rear->_next = node;
}
else
{
_front = node;
}
_rear = node;
_size++;
return node;
}
template<typename T_data>
inline void QueueByLink<T_data>::dequeue()
{
if (_front)
{
NodeQueue<T_data>* next = _front->_next;
_front->_next = nullptr;
delete _front;
_front = next;
_size--;
if (!next)
{
_rear = nullptr;
}
}
}
template<typename T_data>
inline NodeQueue<T_data>* QueueByLink<T_data>::front()
{
return _front;
}
template<typename T_data>
inline NodeQueue<T_data>* QueueByLink<T_data>::rear()
{
return _rear;
}
template<typename T_data>
inline QueueByLink<T_data>::QueueByLink(size_t capacity):
_size(0) , _capacity(capacity), _front(nullptr), _rear(nullptr)
{
if (_capacity > MAX_CAPACITY)
{
_capacity = MAX_CAPACITY;
}
}
template<typename T_data>
inline QueueByLink<T_data>::~QueueByLink()
{
clear();
}
template<typename T_data>
inline void QueueByLink<T_data>::print()
{
NodeQueue<T_data>* node = _front;
while (node)
{
std::cout << "{" << node->_entry._data << "},";
node = node->_next;
}
}
数组实现
/*数组实现的每个元素就是一个条目entry*/
template<typename T_data>
class QueueByArray
{
public:
static constexpr size_t MAX_CAPACITY = 128;
public:
QueueByArray(const size_t capacity = MAX_CAPACITY);
~QueueByArray();
size_t size() { return _size; }
bool empty() { return _size == 0; }
void clear();
size_t enqueue(const EntryQueue<T_data>& entry);
void dequeue();
size_t front();
size_t rear();
private:
size_t _size, _capacity;
int64_t _front, _rear;
std::shared_ptr<EntryQueue<T_data>>* _array;
private:
void print();
friend void test_queuebyarray();
};
template<typename T_data>
inline QueueByArray<T_data>::QueueByArray(const size_t capacity):
_size(0),_capacity(capacity), _front(-1), _rear(-1)
{
if (_capacity > MAX_CAPACITY)
{
_capacity = MAX_CAPACITY;
}
_array = new std::shared_ptr<EntryQueue<T_data>>[_capacity];
}
template<typename T_data>
inline QueueByArray<T_data>::~QueueByArray()
{
delete[] _array;
}
template<typename T_data>
inline void QueueByArray<T_data>::clear()
{
_front = _rear;
}
template<typename T_data>
inline size_t QueueByArray<T_data>::enqueue(const EntryQueue<T_data>& entry)
{
if (_front == -1) _front++ ;//首个元素
if (_rear == (_capacity - 1))
{
std::cout << "\nQueueByArray Is Full!!!" << std::endl;
return -1;
}
_array[++_rear] = std::make_shared<EntryQueue<T_data>>(entry);
_size++;
return _rear;
}
template<typename T_data>
inline void QueueByArray<T_data>::dequeue()
{
if (_front < 0 || _front >= _capacity)
{
std::cout << "\nQueueByArray invalid position " << _front << std::endl;
return;
}
else
{
_front++;
}
_size--;
}
template<typename T_data>
inline size_t QueueByArray<T_data>::front()
{
return _front;
}
template<typename T_data>
inline size_t QueueByArray<T_data>::rear()
{
return _rear;
}
template<typename T_data>
inline void QueueByArray<T_data>::print()
{
for (size_t i = _front; i <= _rear; i++)
{
std::shared_ptr<EntryQueue<T_data>> &entry = _array[i];
std::cout << entry->_data << ",";
}
}
inline void test_queuebyarray()
{
QueueByArray<int> queue_array;
for (size_t i = 0; i < 129; i++)
{
EntryQueue<int> entry(i);
queue_array.enqueue(entry);
}
std::cout << "queue_array size after enqueue " << queue_array.size()<<std::endl;
queue_array.print();
for (size_t i = 0; i < 129; i++)
{
queue_array.dequeue();
}
std::cout << "\nqueue_array size after dequeue " << queue_array.size() << std::endl;
queue_array.print();
queue_array.clear();
std::cout << "\nqueue_array size after clear " << queue_array.size() << ",front:" << queue_array.front() << ",rear:" << queue_array.rear() << std::endl;
}
测试
#include <iostream>
#include "myqueue.hpp"
int main()
{
test_queuebyarray();
std::cout << "\n\n";
test_queuebylist();
}
结果
总结:当节点数目较少,建议使用数组实现,效率更高,需要更高容量的使用链表实现 。