队列简称队,它是一种操作受限的线性表,仅允许在一端进行插入操作,而在另一端进行删除操作。
进行插入的一端叫做队尾; 进行删除的一端叫做队首。 插入操作叫做入队或进队;删除操作叫出队或离队。
与栈的先进后出 不同,元素进出队的次序是先进先出。 队根据数据存储结构的不同也分为顺序队和链队。

一、顺序队
1.对顺序队操作四个非常重要的要素。
- 队空的条件:q->front == q->rear。
- 队满的条件:q->rear == MaxSize-1(data数组的最大下标)。
- 元素e的进队操作:先将rear增1,然后将元素e放在data数组的rear位置。
- 出队操作:先将front增1,然后取出data数组中front位置的元素。
顺序队操作过程示意图

2.顺序队核心算法实现
#define MaxSize 50
typedef int ElemType;
typedef struct
{
ElemType data[MaxSize];
int front,rear;//队首和队尾指针
}SqQueue;
void InitQueue(SqQueue * &q)
{
q = (SqQueue*)malloc(sizeof(SqQueue));
q->front = q->rear = -1;
}
void DestoryQueue(SqQueue * &q)
{
free(q);
}
bool QueueEmpty(SqQueue * q)
{
return (q->front == q->rear);
}
//进队
bool enQueue(SqQueue * &q, ElemType e)
{
if (q->rear == MaxSize - 1)//队满
return false;
q->rear++;
q->data[q->rear] = e;
return true;
}
//出队
bool deQueue(SqQueue * &q, ElemType &e)
{
if (q->front == q->rear)//队空
return false;
q->front++;
e = q->data[q->front];
return true;
}
把数组data的前端和后端连接起来,形成一个环形数组,即把存储队列元素的数组逻辑上看成一个环,称为环形队列。
环形队列首尾相连后,当队尾指针 q->rear = MaxSize - 1后,再前进一个位置就到达 0 ,于是就可以使用另一端的空位置存放队列元素了。实际上存储器中的地址总是连续的,为此采用求余运算(%)来实现:
- 队首指针 front 循环增 1:q->front = (q->front + 1) % MaxSize
- 队尾指针 rear 循环增 1:q->rear = (q->rear + 1) % MaxSize
环形队操作的几种状态。

3.环形队列核心算法实现
void InitQueue(SqQueue * &q)
{
q = (SqQueue*)malloc(sizeof(SqQueue));
q->front = q->rear = 0;
}
void DestoryQueue(SqQueue * &q)
{
free(q);
}
bool QueueEmpty(SqQueue * q)
{
return (q->front == q->rear);
}
//进队
bool enQueue(SqQueue * &q, ElemType e)
{
if ((q->rear + 1) % MaxSize == q->front)//队满
return false;
q->rear = (q->rear + 1) % MaxSize;
q->data[q->rear] = e;
return true;
}
//出队
bool deQueue(SqQueue * &q, ElemType &e)
{
if (q->front == q->rear)//队空
return false;
q->front = (q->front + 1) % MaxSize;
e = q->data[q->front];
return true;
}
一、链队
1.对链队操作四个非常重要的要素。
- 队空的条件:q->rear == NULL(或q->front == NULL)。
- 队满的条件:不考虑。
- 元素e的进队操作:新建一个结点存放元素e(由p指向它),将结点p插入作为队尾结点,让rear指向这个新的尾结。
- 出队操作:取出队首结点(rear所指向的结点的后继结点)的data值并将其删除。
需要注意的是,在链队进队和出队操作后链
- 为空
- 或者为一个不带头节点的由尾结点指针rear唯一标识的循环单链表
不能改变其结构特性。
2.链队核心算法实现
typedef int ElemType;
typedef struct qnode
{
ElemType data;
struct qnode * next;
}DataNode;
typedef struct
{
DataNode * front; //队首
DataNode * rear; //队尾
}LinkQueue;
void InitQueue(LinkQueue * &q)
{
q = (LinkQueue*)malloc(sizeof(LinkQueue));
q->front = q->rear = NULL;
}
void DestoryQueue(LinkQueue * &q)
{
DataNode * pre = q->front, *p; //pre指向队首结点
if (pre != NULL)
{
p = p->next; //p指向结点pre的后继结点
while (p != NULL) //p不空循环
{
free(pre); //释放pre结点
pre = p;
p = p->next; //p,pre同步后移
}
free(pre); //释放最后一个结点
}
free(q); //释放链队结点
}
bool QueueEmpty(LinkQueue * q)
{
return (q->rear == NULL);
}
//进队
void enQueue(LinkQueue * &q, ElemType e)
{
DataNode * p;
p = (DataNode*)malloc(sizeof(DataNode));
p->data = e;
p->next = NULL;
if (q->rear == NULL) //如果队为空则,新结点既是队首结点又是队尾结点
q->front = q->rear = p;
else //链队不为空
{
q->rear->next=p; //将p链到队尾,并将rear指向它
q->rear = p;
}
}
//出队
bool deQueue(LinkQueue * &q, ElemType &e)
{
DataNode * t;
if (q->rear == NULL) //队空
return false;
t = q->front; //t指向首结点
if (q->front == q->rear) //原来队列只有一个数据结点时
q->front = q->rear = NULL;
else //原来队列只有两个及以上数据结点时
q->front = q->front->next;
e = t->data;
free(t);
return true;
}
队列是一种线性表,遵循先进先出原则,分为顺序队和链队。顺序队利用环形数组实现,通过求余运算处理队首队尾指针的增减;链队则通过结点插入和删除操作维护队列。队空和队满的判断条件在顺序队和链队中有不同体现。

1335

被折叠的 条评论
为什么被折叠?



