和栈相反,队列是FIFO表,先进先出。故名思议,和排队打饭一样,先入队的先打完出去,而且只能从队列的尾端加入(插队的滚粗啊。。)。用数组实现队列的话,循环队列是一般是必须的。我们会用2个下标head and tail来标记队头和队尾的位置,如果有人出队的话,head就会+1,入队tail+1,这样整个队列在数组中的位置就会慢慢向右移动,不做处理的话很快会到达数组的尾端。因此,循环队列的采取这样的操作,当队头或者队尾超出存储队列的预设长度的话,就把他们置为0,等于再从数组的左边开始向右增长,形成“卷绕”。
开始时,我们把head和tail初始化为0,这时的队列是空的,此后我们也可以用head == tail 这条语句来判断一个队列是否为空。
NOTE:采用这种判断条件的话,对于规模为N的数组来说只能规模为N - 1的队列,因为如果此时再入队一个对象,tail == head就成立了,意味着队列为空,这不符合逻辑。
判断队列满有两种情况:
1. 此时head为0,tail = length - 1,意味着已经有N - 1个对象在队列里。
2. head大于0,则队列满的条件为head = tail + 1,这种情况画个图就明白了,是由于“卷绕”造成的。
这是算法导论上的示意图。下面贴下我简单实现的代码,C++写的模板类
#ifndef _QUEUE_H_
#define _QUEUE_H_
template <class T>
class Queue
{
private:
int head;
int tail;
int length;
T* array;
public:
Queue(){tail = head = length = 0;}
Queue(int size);
~Queue();
bool isEmpty();
bool isFull();
void enQueue(T val);
T deQueue();
};
template <class T>
Queue<T>::Queue(int size)
{
tail = head = 0;
length = size;
array = new T[size];
}
template <class T>
Queue<T>::~Queue()
{
delete [] array;
}
template <class T>
bool Queue<T>::isEmpty()
{
return head == tail;
}
template <class T>
bool Queue<T>::isFull()
{
return (head == tail + 1) || (tail - head == length - 1);
}
template <class T>
void Queue<T>::enQueue(T val)
{
if(isFull())
{
std::cout << "Queue overflow!" << std::endl;
/*
exit or someting else
*/
}
else
{
array[tail++] = val;
if(tail == length)
tail = 0;
}
}
template <class T>
T Queue<T>::deQueue()
{
T ret;
if(isEmpty())
{
std::cout << "Queue is empty!" << std::endl;
/*
exit or someting else
*/
}
else
{
ret = array[head++];
if(head == length)
head = 0;
return ret;
}
}
#endif
两种最基本的线性表写完了,过几天回家写个链表![]()
浙公网安备 33010602011771号