自定义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()等函数的返回值
疑问与需求
- 该队列实现是否有效?老师认为空状态下指针指向数组内位置的设计不佳。
- 代码是否存在问题?自行检查未发现错误。
- 优化方案:无需假设用户不会输入
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
相关产品推荐
相关产品推荐

