目录
1. 概念理解
队列 (Queue) => 定义 和 基本操作
栈(Stack) 是只允许在一段进行插入和删除操作的线性表。 进栈 和 出栈。
队列(Queue) 是允许在一端进行插入,在另一端删除的线性表。 入队 和 出队。实质上是一种操作受限的线性表。
队尾: 允许插入数据的这一端
队头: 允许删除的一端
队列特点: 先进先出 (FIFO)
2. 基本操作
InitQueue(&Q): 初始化队列,构造一个空队列 Q。
DestoryQueu(&Q): 销毁队列。 销毁并释放队列Q所占用的内存空间。
EnQueue(&Q,x): 入队,若队列Q未满,将 x 加入,使之成为新的队尾。
DeQueue(&Q,&x): 出队,若队列Q非空,删除队头元素,并用 x 返回。
GetHead(Q,&x): 读队头元素,若队列Q非空,则将队头元素赋值给 x 。
3. 用顺序存储的方式实现队列
根据 front 和 rear 的指向逻辑,初始化的时候就可以将 front 和 rear 指针都指向 0.
判断队列是否已满是用 Q.rear=MaxSize 吗? 不是的,如果队头元素有出队的话,队头指针会往后移,同时静态数组前面位置空闲了。
取模运算:即取余运算。 两个整数 a,b a%b == a 除以 b 的余数。 在《数论》中,常表示为 a MOD b.
这里将 front 指针和 rear 指针指向同一个位置的话,那就和队列为空的判断条件重合了,显然计算机会懵,不合理。所以必须牺牲一个存储单元!
应该为 Q.front = (Q.front + 1) % MaxSize;
队列元素的个数: (rear+MaxSize-front)% MaxSize !!!!
上面判断队满和队空的操作是牺牲一个存储空间为代价的! 自己写代码和完成项目完全ok了,
但是出题老师不这么想,要求不准浪费这个存储空间时如何处理?
法一:
在这种结构中,当 rear 和 front 指向同一片内存的时候,可以根据 size 的不同来判断是 为空 还是 队满。
size == MaxSize; // 队满 size ==0; // 队空
法二:
初始化时 rear=front=0; tag=0;
显然,只有删除操作才可能导致队空,只有插入操作才可能导致队满。
队满条件: front == rear && tag == 1;
队空条件: front == rear && tag == 0;
===========================================================================
上面的操作都是建立在 队尾指针指向队尾元素的下一个位置 前提条件进行的,考试中也可能碰到队尾指针指向队尾元素这种情况。这种情况下,代码实现存在不同。
队列初始化的时候也需要进行调整:
因为每次入队都是先将队尾指针后移 再往里面插入数据元素,所以在初始化的时候比较合理的方式是:front 指针指向 0 ,rear 指针指向 n-1 位置。
判空:
( Q.rear + 1)% MaxSize == Q.front
判满:
和之前类似,如果都填满数元素的话,就没办法通过头指针和尾指针的位置关系来判断队列是满还是空。
方案一:牺牲一个存储单元
方案二:增加一个辅助变量