在循环队列中,为了高效利用数组空间,采用“循环”方式使用存储区

  1. 循环队列的操作与存储

    • 入队函数(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
  2. 链队列的结构与操作
    链队列使用链表实现,通常包含一个头结点(不存数据),头指针 front 指向头结点,尾指针 rear 指向最后一个数据节点。

    • 队空条件:Q.front == Q.rear && Q.front->next == NULL 或简化为 Q.front == Q.rear(当初始化时两者都指向头结点)。
    • 入队:在尾部插入新节点,并更新 rear 指针。
    • 出队:从头部删除第一个有效节点,释放内存并更新 front->nextfront 指针。
  3. 队列的应用场景

    • 打印队列:多个任务提交到打印机,按先后顺序排队处理。
    • 操作系统任务调度:进程按到达时间进入就绪队列,等待CPU调度。
    • 广度优先搜索(BFS):图或树遍历时使用队列保存待访问节点。
    • 离散事件模拟:如银行叫号系统、交通灯控制系统等,事件按发生时间排队处理。
  4. 串的定义与特性
    串(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)

通过将队列的存储空间首尾相连,形成逻辑上的环形结构,使得当 rearfront 指针到达数组末尾时,可以“绕回”到数组开头继续使用空闲空间,从而有效避免假溢出。

具体实现机制:

  • 使用模运算(取余 %)实现指针的循环移动:
    • 入队时: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;
}

总结:

解决“假溢出”的关键 是采用循环结构 + 模运算,并合理设计队空/队满判别条件,从而充分利用数组空间,提升存储效率。
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Bol5261

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值