目录
1.队列是在表尾插入元素,在表头删除元素(头删尾插)。队列也分为顺序队列和链式队列。
一、队列的基本知识
1.队列是在表尾插入元素,在表头删除元素(头删尾插)。队列也分为顺序队列和链式队列。
2.队列的特点:先进先出。(排队问题就是先进先出)
3.队列的相关案例:舞伴问题
二、顺序队列
(1) 入栈移动rear指针,出栈移动front指针
就算下面有空位置,也不可以入队了。
(2) 为了解决这个问题,我们可以将队列看作循环的顺序表,也就是循环队列,当rear指针达到最大值后又回到0。具体的,我们可以与表长取模%
(3) 但在循环队列里,队空和队满时,rear指针都等于front指针,这样就难以判断到底是队空还是队满,解决这个问题可以有三个办法
这里介绍第三种方法:
当rear指针+1就与front指针重合时,我们就看作已经队满了,这个位置就不能再放元素进去了。
空队仍保持rear等于front
三、顺序循环队列的基本操作
1.顺序循环队列的定义
typedef struct
{
int *array; //表示数组
int front; //头指针,虽然说是指针,但实际是用的数组的下标,所以是int,而不是int*
int rear; //尾指针
}SqQueue;
2.顺序循环队列的初始化
void initQueue(SqQueue &Q)
{
Q.array = new int[MAXSIZE]; //给数组分配空间
//如果分配失败
if(!Q.array)
{
return;
}
Q.front = Q.rear = 0;
}
3.求顺序循环队列的长度
int QueueLength(SqQueue &Q)
{
return ((Q.rear - Q.front + MAXSIZE) % MAXSIZE);
}
4. 顺序循环队列的入队
void inQueue(SqQueue &Q, int e)
{
//先判断是否队满再入队
//如果队满了
if((Q.rear + 1) % MAXSIZE == Q.front)
{
return;
}
Q.array[Q.rear] = e; //将新元素放到队尾的位置
Q.rear = (Q.rear + 1) % MAXSIZE; //循环队列的尾指针++
}
5.顺序循环队列的出队
void outQueue(SqQueue &Q, int e)
{
//先判断队列里还有没有元素
//如果队空了
if(Q.rear == Q.front)
{
return;
}
e = Q.array[Q.front];
Q.front = (Q.front + 1) % MAXSIZE;
}
6.取对头元素
int GetHead(SqQueue &Q)
{
//先判断队列是否为空
//如果队列不为空
if(Q.rear != Q.front)
{
return Q.array[Q.front];
}
}
四、链队列
如果无法知道队列所需要的长度,则可以用队列的链式表示
五、链队列的基本操作
1.链队列的定义
typedef struct QueueNode
{
int data;
struct QueueNode *next;
}QueueNode; //QueueNode表示一个结点
typedef struct QueueNode *QueuePtr; //QueuePtr是front指针和rear指针的类型
typedef struct
{
QueueNode *front;
QueueNode *rear;
}LinkQueue; //LinkQueue表示链队列
2.链队列的初始化
void initQueue(LinkQueue &Q)
{
Q.front = Q.rear = new QueuePtr;
Q.front->next = NULL;
}
3.销毁链队列
依次释放所有结点,队列本身还存在
void destroyQueue(LinkQueue &Q)
{
while(Q.front != NULL) //注意这里循环的条件不是Q.front->next != NULL
{
QueuePtr p = new QueuePtr;
//这里就表示这是带头结点的链队列
p = Q.front->next;
delete Q.front;
Q.front = p;
}
}
或者不需要另外的指针p,直接用尾指针
void destroyQueue(LinkQueue &Q)
{
while(Q.front != NULL) //注意这里循环的条件不是Q.front->next != NULL
{
Q.rear = Q.front->next;
delete Q.front;
Q.front = Q.rear;
}
}
4.链队列的入队
void inQueue(LinkQueue &Q, int e)
{
QueuePtr p = new QueuePtr;
p->data = e;
p->next = NULL;
Q.rear->next = p;
Q.rear = p;
}
5.链队列的出队
void outQueue(LinkQueue &Q, int e)
{
//先判断队列是否为空
//如果是队空
if(Q.front == Q.rear)
{
return;
}
QueuePtr p = new QueuePtr;
p = Q.front->next;
e = p->data;
Q.front->next = p->next; //注意这里不是Q.front = P->next,如果这样写,头结点就没了
/*这里要注意,如果出队的是最后一个结点,而尾指针是指向最后一个结点的,那么在删除结点前要将尾指针改一下
不然尾指针就成野指针了*/
if(Q.rear == p)
{
Q.rear = Q.front;
}
delete p;
}