队列
- 队列是只允许在一端进行插入,而在另一端进行删除的线性表
- 队头(Front):允许删除的一端,又称为队首。
- 队尾(Rear): 允许插入的一端。
- 先进入队列的元素必然先离开队列,即先进先出(First In First Out)简称FIFO
顺序队列 - 用数组来实现队列,可以将队首放在数组下标为0的位置。
循环队列 - 把数组“掰弯”,形成一个环。Rear指针到了下标为4的位置还能继续指回到下标为0的地方。这样首尾相连的顺序存储的队列就叫循环队列
- 入队:rear=(rear+1)%MaxSize
- 出队:front=(front+1)%MaxSize
- 循环队列的操作
- 1.入队
- 2.出队
- 概要: 那如何分辨队列是空还是满呢?
* 方法一:设置标志位flag,当flag=0且rear等于front时为队列空,当flag=1且rear等于front时为队列满。
* 方法二:我们把front=rear仅作为队空的判定条件。当队列满的时候,令数组中仍然保留一个空余单元。我们认为这种情况就是队列满了。
链式队列 - 队列的链式存储结构,其实就是线性表的单链表,只不过需要加点限制,只能表尾插入元素,表头删除元素。
- 为了方便操作,我们分别设置队头指针和队尾指针,队头指针指向头结点,队尾指针指向尾结点。
- 链式队列的操作
- 1.入队:我们知道队列只能从队尾插入元素,队头删除元素。于是入队就是在队尾指针进行插入结点操作。链队的插入操作和单链表的插入操作是一致的。
- 2.出队:出队就是头结点的后继结点出队,然后将头结点的后继改为它后面的结点。
双端队列 - 双端队列是指允许两端都可以进行入队和出队操作的队列
循环队列的顺序存储实现
队列的顺序存储结构通常由一个一维数组和一个记录队列头元素位置的变量 front 以及一个记录队列尾元素位置的变量 rear 组成,其中 front 指向整个队列的头一个元素的再前一个,rear 指向的是整个队列的最后一个元素,从 rear 入队,从
#include<stdio.h>
#include<malloc.h>
#define MaxSize 100
typedef int ElementType;
typedef struct QNode *Queue;
struct QNode{
ElementType Data[MaxSize];
int front; // 记录队头
int rear; // 记录队尾
};
Queue CreateQueue(); // 初始化队列
void AddQ(Queue Q,ElementType item); // 入队
int IsFull(Queue Q); // 判断队列是否已满
ElementType DeleteQ(Queue Q); // 出队
int IsEmpty(Queue Q); // 判断队列是否为空
// 初始化
Queue CreateQueue(){
Queue Q;
Q = (Queue)malloc(sizeof(struct QNode));
Q->front = -1;
Q->rear = -1;
return Q;
}
// 判断队列是否已满
int IsFull(Queue Q){
return ((Q->rear+1) % MaxSize == Q->front);
}
// 入队
void AddQ(Queue Q,ElementType item){
if(IsFull(Q)){
printf("队列满");
return;
}else{
Q->rear = (Q->rear+1) % MaxSize;
Q->Data[Q->rear] = item;
}
}
//判断队列是否为空
int IsEmpty(Queue Q){
return (Q->front == Q->rear);
}
// 出队
ElementType DeleteQ(Queue Q){
if(IsEmpty(Q)){
printf("队列空");
return 0;
}else{
Q->front = (Q->front+1) % MaxSize;
return Q->Data[Q->front];
}
}
int main(){
Queue Q;
Q = CreateQueue();
AddQ(Q,3);
printf("3入队\n");
AddQ(Q,5);
printf("5入队\n");
AddQ(Q,11);
printf("11入队\n");
printf("%d出队\n",DeleteQ(Q));
printf("%d出队\n",DeleteQ(Q));
return 0;
}
队列的链式存储实现
队列的链式存储结构也可以用一个单链表实现。插入和删除操作分别在链表的两头进行,front 在链表头,rear 在链表尾,从 rear 入队,从 front 出队
#include<stdio.h>
#include<malloc.h>
typedef int ElementType;
typedef struct QNode *Queue;
struct Node{
ElementType Data;
struct Node *Next;
};
struct QNode{
struct Node *rear; // 指向队尾结点
struct Node *front; // 指向队头结点
};
Queue CreateQueue(); // 初始化队列
void AddQ(Queue Q,ElementType item); // 入队
ElementType DeleteQ(Queue Q); // 出队
int IsEmpty(Queue Q); // 判断队列是否为空
// 初始化
Queue CreateQueue(){
Queue Q;
Q = (Queue)malloc(sizeof(struct QNode));
Q->front = NULL;
Q->rear = NULL;
return Q;
}
// 是否为空
int IsEmpty(Queue Q){
return (Q->front == NULL);
}
// 入队
void AddQ(Queue Q,ElementType item){
struct Node *node;
node = (struct Node *)malloc(sizeof(struct Node));
node->Data = item;
node->Next = NULL;
if(Q->rear==NULL){ //此时队列空
Q->rear = node;
Q->front = node;
}else{ //不为空
Q->rear->Next = node; // 将结点入队
Q->rear = node; // rear 仍然保持最后
}
}
// 出队
ElementType DeleteQ(Queue Q){
struct Node *FrontCell;
ElementType FrontElem;
if(IsEmpty(Q)){
printf("队列空");
return 0;
}
FrontCell = Q->front;
if(Q->front == Q->rear){ // 队列中只有一个元素
Q->front = Q->rear = NULL;
}else{
Q->front = Q->front->Next;
}
FrontElem = FrontCell->Data;
free(FrontCell);
return FrontElem;
}
int main(){
Queue Q;
Q = CreateQueue();
printf("入队5\n");
AddQ(Q,5);
printf("入队4\n");
AddQ(Q,4);
printf("入队4\n");
AddQ(Q,3);
printf("出队%d\n",DeleteQ(Q));
printf("出队%d\n",DeleteQ(Q));
printf("出队%d\n",DeleteQ(Q));
printf("%d\n",DeleteQ(Q));
return 0;
}