-
循环队列的操作与存储
- 入队函数(EnQueue):
在循环队列中,为了高效利用数组空间,采用“循环”方式使用存储区。入队时首先判断队列是否已满,判断条件为(Q->rear + 1) % MAXQSIZE == Q->front。如果相等说明队列满,不能入队;否则将新元素放入Q->data[Q->rear],然后更新尾指针:Q->rear = (Q->rear + 1) % MAXQSIZE。 - 出队函数(DeQueue):
出队前判断队列是否为空,判断条件是Q->front == Q->rear。若为空则无法出队;否则取出Q->data[Q->front]的元素,并更新头指针:Q->front = (Q->front + 1) % MAXQSIZE。
- 入队函数(EnQueue):
-
链队列的结构与操作
链队列使用链表实现,通常包含一个头结点(不存数据),头指针front指向头结点,尾指针rear指向最后一个数据节点。- 队空条件:
Q.front == Q.rear && Q.front->next == NULL或简化为Q.front == Q.rear(当初始化时两者都指向头结点)。 - 入队:在尾部插入新节点,并更新
rear指针。 - 出队:从头部删除第一个有效节点,释放内存并更新
front->next和front指针。
- 队空条件:
-
队列的应用场景
- 打印队列:多个任务提交到打印机,按先后顺序排队处理。
- 操作系统任务调度:进程按到达时间进入就绪队列,等待CPU调度。
- 广度优先搜索(BFS):图或树遍历时使用队列保存待访问节点。
- 离散事件模拟:如银行叫号系统、交通灯控制系统等,事件按发生时间排队处理。
-
串的定义与特性
串(String)是由零个或多个字符组成的有限序列,记作 S = ‘a₁a₂…aₙ’(n ≥ 0)。- 是一种特殊的线性表,其数据元素为字符。
- 支持整体操作,如比较、连接、复制、子串查找等。
- 常见应用包括文本处理、编译器词法分析、数据库记录字段(如姓名、地址)等。
- 存储方式有定长顺序存储、堆分配存储和链式存储等多种形式。
// 示例:循环队列的基本结构定义
#define MAXQSIZE 100
typedef struct {
char data[MAXQSIZE];
int front; // 头指针,指向队头元素
int rear; // 尾指针,指向下一个插入位置
} SqQueue;
// 入队操作示例
int EnQueue(SqQueue *Q, char e) {
if ((Q->rear + 1) % MAXQSIZE == Q->front) {
return 0; // 队列满
}
Q->data[Q->rear] = e;
Q->rear = (Q->rear + 1) % MAXQSIZE;
return 1;
}
// 出队操作示例
int DeQueue(SqQueue *Q, char *e) {
if (Q->front == Q->rear) {
return 0; // 队列空
}
*e = Q->data[Q->front];
Q->front = (Q->front + 1) % MAXQSIZE;
return 1;
}
循环队列中的“假溢出”问题是指:尽管队列的实际元素个数未达到最大容量,但由于顺序队列的线性存储结构限制,尾指针已到达数组末尾,导致无法继续插入元素的现象。这种现象是“假”的溢出,因为数组前面可能存在空闲空间。
解决方法:使用循环队列(Circular Queue)
通过将队列的存储空间首尾相连,形成逻辑上的环形结构,使得当 rear 或 front 指针到达数组末尾时,可以“绕回”到数组开头继续使用空闲空间,从而有效避免假溢出。
具体实现机制:
- 使用模运算(取余
%)实现指针的循环移动:- 入队时:
Q->rear = (Q->rear + 1) % MAXQSIZE - 出队时:
Q->front = (Q->front + 1) % MAXQSIZE
- 入队时:
- 队满判断条件:
(Q->rear + 1) % MAXQSIZE == Q->front - 队空判断条件:
Q->front == Q->rear
⚠️ 注意:由于队空和队满时都有
front == rear,因此必须采用牺牲一个存储单元的方法来区分队空与队满(即上述队满判断条件),或者引入额外计数器size或标志位进行区分。
示例代码片段(带注释):
typedef struct {
int data[MAXQSIZE];
int front;
int rear;
} SqQueue;
// 入队操作
int EnQueue(SqQueue *Q, int e) {
if ((Q->rear + 1) % MAXQSIZE == Q->front) {
return 0; // 队列满(防止假溢出后的真满)
}
Q->data[Q->rear] = e;
Q->rear = (Q->rear + 1) % MAXQSIZE; // 循环更新
return 1;
}
// 出队操作
int DeQueue(SqQueue *Q, int *e) {
if (Q->front == Q->rear) {
return 0; // 队列空
}
*e = Q->data[Q->front];
Q->front = (Q->front + 1) % MAXQSIZE; // 循环更新
return 1;
}
总结:
✅ 解决“假溢出”的关键 是采用循环结构 + 模运算,并合理设计队空/队满判别条件,从而充分利用数组空间,提升存储效率。


986

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



