一、队列的概念及结构
1.队列的概念
队列:只允许在一端进行插入数据操作,在另一端进行删除数据操作的特殊线性表,队列具有先进先出FIFO(First In First Out) 入队列:进行插入操作的一端称为队尾 出队列:进行删除操作的一端称为队头。
2.队列的结构
二、队列的实现
队列也可以数组和链表的结构实现,使用链表的结构实现更优一些,因为如果使用数组的结构,出队列在数组头上出数据,效率会比较低。因此下面我们基于链表来实现队列:
1.定义用链表表示的队列struct QueueNode
typedef struct QListNode
{
struct QListNode* _next;
QDataType _data;
}QNode;
2.定义队列的队头、队尾指针struct Queue
// 队列的结构
typedef struct Queue
{
QNode* _front;
QNode* _rear;
int size;
}Queue;
3.队列的初始化函数QueueInit
// 初始化队列
void QueueInit(Queue* q)
{
q->_front = q->_rear = NULL;
q->size = 0;
}
4.队列的销毁函数QueueDestroy
遍历队列,记住free前先存储下一个节点的地址。
// 销毁队列
void QueueDestroy(Queue* q)
{
assert(q);
QNode* cur = q->_front;
while(cur)
{
QNode* next = cur -> _next;
free(cur);
cur = next;
}
q->size = 0;
q->_front = q->_rear = NULL;
}
5.队列的队尾入数据函数QueuePush
先开辟一个结点,在分两种情况,一种情况队列一个节点都没有,那可以直接当节点,第二种情况队列一开始有节点,尾插数据即可。
// 队尾入队列
void QueuePush(Queue* q, QDataType data)
{
QNode* newnode = (QNode*)malloc(sizeof(QNode));
if (newnode == NULL)
{
perror("malloc fail");
return;
}
newnode->_data = data;
newnode->_next = NULL;
//队列有节点
if (q->size > 0)
{
q->_rear->_next = newnode;
q->_rear = newnode;
q->size++;
}
//队列没有节点
else
{
q->_front = q->_rear = newnode;
q->size++;
}
}
6.队列的队头出数据函数QueuePop
代码如下:
// 队头出队列
void QueuePop(Queue* q)
{
assert(q);
assert(!QueueEmpty(q));
QNode* next = q->_front->_next;
free(q->_front);
q->_front = next;
if (q->_front == NULL)
q->_rear = NULL;
q->size--;
}
7.队列的取出队头数据函数QueueFront
记住每次取数据前判断队列是否为空,不为空才进行下一步。
代码如下:
// 获取队列头部元素
QDataType QueueFront(Queue* q)
{
assert(q);
assert(!QueueEmpty(q));
return q->_front->_data;
}
8.队列的取出队尾数据函数QueueBack
记住每次取数据前判断队列是否为空,不为空才进行下一步。
代码如下:
// 获取队列队尾元素
QDataType QueueBack(Queue* q)
{
assert(q);
assert(!QueueEmpty(q));
return q->_rear->_data;
}
9.队列是否为空函数QueueEmpty
代码如下:
// 检测队列是否为空,如果为空返回true,如果非空返回false
bool QueueEmpty(Queue* q)
{
return q->size == 0;
}
10.队列的长度函数QueueSize
代码如下:
// 获取队列中有效元素个数
int QueueSize(Queue* q)
{
return q->size;
}