文章目录
1.队列的基本概念
定义:队列也是一种操作受限的线性表,只允许在表的一端进行插入,另一端进行删除。
概念:向队列中插入元素称为入队,删除元素成为出队。
操作特性为:先进先出
2.队列的基本操作
1.存储类型
typedef struct queue{
int front;
int rear;
Datetype *base;
}Queue;
2.加溢出
在图a中,此时为队列的初始状态,有Q.frontQ.rear0成立,该条件可以作为判断对空的条件。但却不能用Q.rear==MaxSize,在图d中,队列中仅有一个元素,仍满足该条件。这时入队出现假溢出。但这种溢出不是真正的溢出,在数组中仍存在可以存放数据元素的空位置,所以是一种假溢出。
解决假溢出的方法:
1.按最大可能的进队列操作次数,设置顺序队列的最大元素个数,这种方法很浪费空间,而且有时会因为估计不准而出错;
2.修改出队列算法,设每次出队列后,都把队列中剩余数据元素向队头方向移用一个位置,时间复杂度为O(n),浪费了时间。
3.修改入队列算法,当为真溢出时,返回false;当为假溢出时,则把队列中的数据元素向队头方向移动front+1个位置,使队头元素位于队列的最前端后再完成新数据元素的入队操作;当为其它情况时,进队列操作算法同前。此算法的时间复杂度也为O(n)。
3.循环队列
为了解决假溢出的问题,引入了循环队列。将顺序队列臆想为一个环状的空间,即把存储队列元素的表从逻辑上视为一个环,称为循环队列。当队首指针Q.front==MaxSize-1后,就在进一个位置,自动到0。
那么如何确定不同的队空、队满的判定条件?
方法一:附设一个存储队列中元素个数的变量num,当 num=0时队空,当num=QueueSize时为队满;
方法二:修改队满条件,浪费一个元素空间,队满时数组 中只有一个空闲单元;
方法三:设置标志flag,当 front-rear且flag=0时为队空,当 frontrear且flag=1时为队满。
4.循环队列的基本操作(完整代码(github))
1.初始化
//初始化队列
Status InitQueue(Queue * queue)
{
queue->base=(Datetype *)malloc(sizeof(Datetype)*MaxSize);
if(!queue->base) exit(-1);
queue->front=queue->rear=0;
return 1;
}
2.判断对空
//判断队列是否为满
Status isFull(Queue *q)
{
if((q->rear+1)%MaxSize==q->front) return 1;
else return 0;
}
3.判断队满
//判断队列是为空
Status isEmpty(Queue *q)
{
if(q->front==q->rear) return 1;
else return 0;
}
4.入队
//入队
Status Enqueue(Queue *q,Datetype e)
{
if(isFull(q)) return 0;//如果队列为满,返回false
q->base[q->rear]=e;
q->rear=(q->rear+1)%MaxSize;
return 1;
}
5.出队
//出队
Status Dequeue(Queue *q)
{
if(isEmpty(q)) return 0;
q->front=(q->front+1)%MaxSize;
return 1;
}
3.链式队列(完整代码(github))
1.存储类型
// 队列的节点
struct Node
{
int data;
struct Node* next;
};
// 队首队尾指针
struct Queue
{
struct Node* front;
struct Node* rear;
int size;
};
出对时,首先判断队是否为空若不为空,则将其从链表中摘除,并让Q.front指向下一个结点,入队时,建立一个新的结点,将新节点插入到链表的尾部去,并让Q.rear指向这个新插入的结点。
基本操作:
1.初始化
// 队列的节点
struct Node
{
int data;
struct Node* next;
};
// 队首队尾指针
struct Queue
{
struct Node* front;
struct Node* rear;
int size;
};
2.判断对空
bool QueueEmpty(struct Queue* queue)
{
if(Q.front==Q.rear) return ture;
else return false;
}
3.入队
//入队
void QueuePush(struct Queue* queue, const int data)
{
struct Node* node;
node = (struct Node*)malloc(sizeof(struct Node));
assert(node != NULL);
node->data = data;
node->next = NULL;
if(QueueEmpty(queue))
{
queue->front = node;
queue->rear = node;
}
else
{
queue->rear->next = node;
queue->rear = node;
}
++queue->size;
}
4.出队
//入队
void QueuePush(struct Queue* queue, const int data)
{
struct Node* node;
node = (struct Node*)malloc(sizeof(struct Node));
assert(node != NULL);
node->data = data;
node->next = NULL;
if(QueueEmpty(queue))
{
queue->front = node;
queue->rear = node;
}
else
{
queue->rear->next = node;
queue->rear = node;
}
++queue->size;
}