You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

自定义front=0、rear=-1的线性队列是否有效?求优化方案

C语言线性队列实现的疑问与优化

原始实现代码

#include <stdio.h>
#include <limits.h>

#define MAX_SIZE 5
#define FULL INT_MAX
#define EMPTY INT_MIN

int Q[MAX_SIZE]; // linear queue //
int rear = -1;
int front = 0;

// condition for empty is Qsize is zero (front > rear)                 //
// condition for full is rear is at last index (rear == MAX_SIZE - 1)  //

// basic operations on Queue // 

int add_Q(int item);     // if full returns (INT_MAX) else  returns item inserted          // 
int delete_item_in_Q(); // if empty returns (INT_MIN) else returns deleted item           // 
size_t Qsize();        // returns 0 if (front > rear) else returns the current size of Q //

// read operations   //

int rear_data();   // if empty returns (INT_MIN) else returns rear data              //
int front_data(); //  if empty returns (INT_MIN) else returns front data            //
void read_Q();

void delete_Q();  
void get_Q(size_t size);

int main(void){
    int size;

    printf("\nenter your size(positive) for Queue (less than %d) : ",MAX_SIZE);
    scanf("%d",&size);

    get_Q(size);
    read_Q();

    add_Q(66);
    read_Q();

    delete_item_in_Q();
    read_Q();

    delete_Q();
    read_Q(); 

return 0;

}

void get_Q(size_t size){
    int item;
    if(size > MAX_SIZE){
        printf("enter valid size \n");
        return;
    }

    for(int i = 0 ; i < size ; i ++){
        printf("enter your queue elements : ");
        scanf("%d",&item);
        add_Q(item);
    }
}

int add_Q(int item){
    return rear == (MAX_SIZE - 1) ? FULL : (Q[++rear] = item); 
}

int delete_item_in_Q(){
    return Qsize() ? Q[front++]:EMPTY; 
}

size_t Qsize(){
    if(front > rear){
        front = 0;rear = -1;
    }
return (rear - front + 1);
}

int front_data(){
    return Qsize() ? Q[front]:EMPTY;
}
int rear_data(){
    return Qsize() ? Q[rear]:EMPTY;
}
void read_Q(){

    if(!Qsize()){
        printf("\nthe queue is empty\n");
        return;
    }

    int i = front;
    printf("\nthe queue is : ");

    while(1){
        printf("%d=>",Q[i++]);

        if(i == MAX_SIZE){
            printf("\nqueue is full\n");
            return;
        }
        else if (i > rear){
            putchar('\n');
            return;
        }
    }

}

void delete_Q(){

    while(1){
        if(!Qsize()){
            printf("\nthe queue is empty\n");
            return;
        }
        printf("the deleted element is : %d\n",Q[front++]);

       }
}

实现说明

  • 初始状态:rear=-1、front=0(不同于常规的front=rear=-1)
  • 空队列判断:front > rear(Qsize()返回0),此时Qsize()会将front和rear重置为初始状态
  • 满队列判断:rear == MAX_SIZE - 1
  • 假设条件:用户不会输入INT_MIN或INT_MAX,未检查scanf()、add_Q()等函数的返回值

疑问与需求

  1. 该队列实现是否有效?老师认为空状态下指针指向数组内位置的设计不佳。
  2. 代码是否存在问题?自行检查未发现错误。
  3. 优化方案:无需假设用户不会输入INT_MIN或INT_MAX,同时优化read_Q()函数的实现。

解答与优化方案

1. 实现有效性与设计评价

你的实现逻辑上是有效的:能够正确完成入队、出队、判空判满、读取队列等核心操作,空队列时的指针重置也能保证后续操作正常执行。

但老师的观点确实有道理:

  • 空状态下front=0指向数组第一个元素,但此时该位置的元素是无效的,容易给人“队列有元素”的误导,若直接访问Q[front]而未判空,会读取到垃圾值。
  • 常规的front=rear=-1设计更直观:空队列时两个指针都处于数组下标范围外,明确表示没有有效元素,降低误解风险。

2. 代码存在的问题

  • read_Q()逻辑错误:当遍历到i == MAX_SIZE时直接判定队列满,这是错误的。例如队列元素范围是front=1到rear=3(MAX_SIZE=5),此时i会走到5,但队列并未满,却会错误输出“queue is full”。
  • 函数副作用问题:Qsize()本应仅返回队列大小,却在空队列时修改front和rear的全局状态,违反“函数职责单一”原则,可能引发意外问题(比如多线程环境下的竞态)。
  • 参数类型不匹配:get_Q()的参数是size_t(无符号类型),但scanf输入的是int size,若用户输入负数,会被转换为超大的无符号数,导致错误判定“size > MAX_SIZE”,应先校验输入的size为正数。
  • 返回值歧义:依赖INT_MIN/INT_MAX表示空/满状态,当用户输入这两个值时,无法区分操作结果是成功还是失败,这也是你需要优化的核心点。

3. 优化方案

3.1 解决返回值歧义问题

修改函数接口,用返回值表示操作成功/失败,通过指针参数传递实际元素,避免与INT_MIN/INT_MAX冲突:

#include <stdio.h>
#include <stdbool.h>

#define MAX_SIZE 5

int Q[MAX_SIZE];
int rear = -1;
int front = 0;

// 判空
bool is_empty() {
    return front > rear;
}

// 判满
bool is_full() {
    return rear == MAX_SIZE - 1;
}

// 重置队列(空队列时调用)
void reset_queue() {
    front = 0;
    rear = -1;
}

// 入队:成功返回true,失败返回false
bool enqueue(int item) {
    if (is_full()) {
        return false;
    }
    Q[++rear] = item;
    return true;
}

// 出队:成功返回true,出队元素存入*p;失败返回false
bool dequeue(int *p) {
    if (is_empty()) {
        return false;
    }
    *p = Q[front++];
    // 空队列时重置指针
    if (is_empty()) {
        reset_queue();
    }
    return true;
}

// 获取队首元素:成功返回true,元素存入*p;失败返回false
bool get_front(int *p) {
    if (is_empty()) {
        return false;
    }
    *p = Q[front];
    return true;
}

// 获取队尾元素:成功返回true,元素存入*p;失败返回false
bool get_rear(int *p) {
    if (is_empty()) {
        return false;
    }
    *p = Q[rear];
    return true;
}

3.2 优化read_Q()函数

改用for循环遍历有效元素范围,单独判断队列是否满,避免逻辑错误:

void read_Q() {
    if (is_empty()) {
        printf("\n队列是空的\n");
        return;
    }
    printf("\n队列元素:");
    for (int i = front; i <= rear; i++) {
        printf("%d", Q[i]);
        if (i != rear) {
            printf("=>");
        }
    }
    printf("\n");
    // 单独判断队列是否满
    if (is_full()) {
        printf("队列已满\n");
    }
}

3.3 修复get_Q()参数问题

修改参数类型为int,增加输入合法性校验:

void get_Q(int size) {
    if (size <= 0 || size > MAX_SIZE) {
        printf("请输入1到%d之间的有效大小\n", MAX_SIZE);
        return;
    }
    int item;
    for (int i = 0; i < size; i++) {
        printf("请输入队列元素:");
        // 增加scanf返回值检查,避免输入错误
        if (scanf("%d", &item) != 1) {
            printf("输入无效,终止入队\n");
            // 清空输入缓冲区
            while (getchar() != '\n');
            return;
        }
        if (!enqueue(item)) {
            printf("队列已满,无法继续入队\n");
            return;
        }
    }
}

3.4 优化delete_Q()函数

void delete_Q() {
    int item;
    printf("\n开始清空队列:\n");
    while (dequeue(&item)) {
        printf("已删除元素:%d\n", item);
    }
    printf("队列已清空\n");
}

3.5 优化后的main()函数

int main(void) {
    int size;
    printf("请输入队列大小(1到%d之间):", MAX_SIZE);
    while (scanf("%d", &size) != 1 || size <= 0 || size > MAX_SIZE) {
        printf("输入无效,请重新输入1到%d之间的大小:", MAX_SIZE);
        while (getchar() != '\n'); // 清空输入缓冲区
    }

    get_Q(size);
    read_Q();

    // 测试入队满的情况
    if (!enqueue(66)) {
        printf("\n入队失败:队列已满\n");
    }
    read_Q();

    // 测试出队
    int del_item;
    if (dequeue(&del_item)) {
        printf("\n已出队元素:%d\n", del_item);
    } else {
        printf("\n出队失败:队列是空的\n");
    }
    read_Q();

    delete_Q();
    read_Q();

    return 0;
}

内容的提问来源于stack exchange,提问作者Sai Krishna

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.08 23:37:02