1.队列的概念
只允许在一端插入数据操作,在另一端进行删除数据操作的特殊线性表;进行插入操作的一端称为队尾(入队列),进行删除操作的一端称为队头(出队列);队列具有先进先出(FIFO)的特性。
2.顺序队列
(1)队头不动,出队列时队头后的所有元素向前移动
缺陷:操作是如果出队列比较多,要搬移大量元素。
(2)队头移动,出队列时队头向后移动一个位置
如果还有新元素进行入队列容易造成假溢出。
假溢出:顺序队列因多次入队列和出队列操作后出现的尚有存储空间但不能进行入队列操作的溢出。
真溢出:顺序队列的最大存储空间已经存满二又要求进行入队列操作所引起的溢出。
3.循环队列
循环队列如何进行判空和满操作:
少用一个存储单元
设置一个标记flag;
初始值 flag = 0;入队列:flag = 1; 出队列:flag = 0;
队列为空时:(front == rear && flag == 0)
队列为满时:(front == rear && flag == 1)
设置一个计数器
4.链式队列
链式队列:特殊的单链表,只在单链表上进行头删尾插的操作
***【1.定义一个队列结构体】***】
由于是链式队列,所以先定义一个存放数据域和指针域的结构体
队列结构体中定义一个队头指针和队尾指针
typedef int QElemType;
//typedef struct BTNode* QElemType;
typedef struct QNode
{
QElemType data;
struct QNode *_pNext;
}QNode;
typedef struct LQueue
{
QNode *pFront;
QNode *pRear;
}LQueue;
【2.创建新结点】
//创建新结点
static QNode *BuyLQNode(QElemType data)
{
QNode *pLQNode = (QNode *)malloc(sizeof(QNode));
if (NULL == pLQNode)
{
printf("申请空间失败!\n");
assert(pLQNode);
}
pLQNode->data = data;
pLQNode->_pNext = NULL;
return pLQNode;
}
【3.初始化队列】
void LQueueInit(LQueue *q)
{
assert(q);
q->pFront = q->pRear = NULL;
}
【4.入队列】
判断队中是否有元素
找到队尾元素
让新入队的元素链在原先队列的队尾上,更新新的队尾
void LQueuePush(LQueue *q, QElemType data)
{
assert(q);
if (NULL == q->pFront)
{
q->pFront = q->pRear = BuyLQNode(data);
return;
}
q->pRear->_pNext = BuyLQNode(data);
q->pRear = q->pRear->_pNext;
}
【5.出队列】
这里的出队列采用是让队头元素不断后移,刷新队头元素,这样优化时间效率
void LQueuePop(LQueue *q)
{
assert(q);
QNode *pDel;
if (NULL == q->pFront)
{
return;
}
if (q->pFront == q->pRear)
{
q->pRear = NULL;
}
pDel = q->pFront;
q->pFront = q->pFront->_pNext;
free(pDel);
}