一、顺序队列
队列是一种特殊的线性表,特殊之处在于它只允许在表的前端进行删除操作,而在表的后端进行插入操作,和栈一样,队列是一种操作受限制的线性表。进行插入操作的端称为队尾,进行删除操作的端称为队头。
队列的数据元素又称为队列元素。在队列中插入一个队列元素称为入队,从队列中删除一个队列元素称为出队。因为队列只允许在一端插入,在另一端删除,所以只有最早进入队列的元素才能最先从队列中删除,故队列又称为先进先出线性表。
队列整体来说与栈类似,不过栈的特性是先进后出,二队列的特性是先进先出。
C语言实现:
1、队列的存储结构以及一些需要实现的方法
typedef char ElemType;
#define SIZE 10
#define TRUE 1
#define FALSE 0
typedef struct queue
{
ElemType *data;
int head;
int tail;
}queue, *pQueue;
void InitQueue(pQueue que); //队列的初始化
int PushQue(pQueue que, ElemType val); //入队列
int PopQue(pQueue que, ElemType *res); //出队列
void DestroyQue(pQueue que); //销毁队列
2、队列的判空判满以及初始化
static int IsFull(pQueue que) //判满
{
assert(que != NULL);
if ((que->tail + 1) % SIZE == que->head)
{
return TRUE;
}
return FALSE;
}
static int IsEmpty(pQueue que) //判空
{
assert(que != NULL);
if (que->head == que->tail)
{
return TRUE;
}
return FALSE;
}
void InitQueue(pQueue que) //初始化
{
assert(que != NULL);
que->data = (ElemType*)malloc(sizeof(ElemType)* SIZE);
assert(que->data != NULL);
que->head = que->tail = 0;
}
3、入队列(push)
int PushQue(pQueue que, ElemType val)
{
assert(que != NULL);
if (IsFull(que))
{
return FALSE;
}
que->data[que->tail++] = val;
que->tail %= SIZE;
return TRUE;
}
4、出队列(pop)
int PopQue(pQueue que, ElemType *res)
{
assert(que != NULL && que->data != NULL);
if (IsEmpty(que))
{
return FALSE;
}
*res = que->data[que->head++];
que->head %= SIZE;
return TRUE;
}
5、销毁队列
void DestroyQue(pQueue que)
{
assert(que != NULL);
free(que->data);
que->data = NULL;
que->head = que->tail = 0;
}
这里我实现的是一个循环的顺序队列,当向队列中插入数据时,如果队列已到达队尾,则去判断队列头还有没有可以存储数据的位置,如果有则放在队列头。
C++实现:
typedef int ElemType;
#define SIZE 10
class Queue
{
private:
ElemType *_data;
int _head;
int _tail;
bool IsFull(); //判满
bool IsEmpty(); //判空
public:
Queue();
Queue(const Queue &src); //拷贝构造函数
Queue& operator= (const Queue& src); //等号运算符的重载
~Queue();
bool Push(ElemType val); //入队列
bool Pop(); //出队列
ElemType GetQue(); //去队列头的元素
void show(); //打印整个队列
};
bool Queue::IsFull()
{
assert(this != NULL);
if ((_tail + 1) % SIZE == _head)
{
return true;
}
return false;
}
bool Queue::IsEmpty()
{
assert(this != NULL);
if (_head == _tail)
{
return true;
}
return false;
}
Queue::Queue()
{
assert(this != NULL);
_data = new ElemType[SIZE];
assert(_data != NULL);
_head = 0;
_tail = 0;
}
Queue::Queue(const Queue &src)
{
_data = new ElemType[sizeof(src._data)];
for (int i = src._head; i < src._tail; ++i)
{
_data[src._head] = src._data[i];
}
_head = src._head;
_tail = src._tail;
}
Queue& Queue::operator= (const Queue& src)
{
if (this == &src)
{
return *this;
}
if (_data != NULL)
{
delete[]_data;
}
_data = new ElemType[sizeof(src._data)];
for (int i = src._head; i < src._tail; ++i)
{
_data[src._head] = src._data[i];
}
_head = src._head;
_tail = src._tail;
return *this;
}
Queue::~Queue()
{
if (NULL != _data)
{
delete[]_data;
_data = NULL;
_head = 0;
_tail = 0;
}
}
bool Queue::Push(ElemType val)
{
assert(this != NULL);
if (IsFull())
{
return false;
}
_data[_tail++] = val;
_tail %= SIZE;
return true;
}
bool Queue::Pop()
{
assert(this != NULL && _data != NULL);
if (IsEmpty())
{
return false;
}
_head++;
_head %= SIZE;
return true;
}
ElemType Queue::GetQue()
{
assert(this != NULL);
if (IsEmpty())
{
return 0;
}
return _data[_head];
}
void Queue::show()
{
assert(this != NULL);
for (int i = _head; i < _tail; i++)
{
cout << _data[i] << " ";
}
cout << endl;
}
二、链式队列
在队列的形成过程中,可以利用线性链表的原理,来生成一个队列。
利用链表的队列,要动态创建和删除节点,效率较低,但是可以动态增长。
队列采用的FIFO(first in first out),新元素(等待进入队列的元素)总是被插入到链表的尾部,而读取的时候总是从链表的头部开始读取。每次读取一个元素,释放一个元素。所谓的动态创建,动态释放。因而也不存在溢出等问题。由于链表由结构体间接而成,遍历也方便。
链式队列的实现:
template<typename T>
class Mqueue
Mqueue()
{
public:
{
_head = NULL;
_tail = NULL;
}
~Mqueue()
{
if (_head == NULL)
{
return;
}
while (_head != _tail)
{
pop();
}
delete _head;
_head = _tail = NULL;
}
void push(T val)
{
Node *p = new Node;
p->_val = val;
p->_next = NULL;
if (_head == NULL && _tail == NULL)
{
_head = p;
_tail = p;
}
else
{
_tail->_next = p;
_tail = p;
}
}
int pop()
{
if (_head == NULL)
{
return -1;
}
Node *p = _head;
_head = p->_next;
p->_next = NULL;
delete p;
}
T top()
{
return _tail->_val;
}
void show()
{
Node *p = _head;
while (p != NULL)
{
cout << p->_val << " ";
p = p->_next;
}
cout << endl;
}
private:
class Node
{
private:
T _val;
Node *_next;
friend class Mqueue;
public:
Node()
{
_next = NULL;
}
};
Node *_head;
Node *_tail;
};