行业资讯
📅 2026/8/12 18:09:47
循环队列操作
1. 数学原理余数永远小于除数在数学中当我们计算A 除以 B时得到的余数一定满足一个条件余数必须大于等于 0且严格小于除数 B。也就是说A % n的结果永远只能是0, 1, 2, ..., n-1其中的一个数字。它绝对不可能等于n也绝对不可能大于n。而一个长度为n的数组它的合法下标正好就是0到n-1。因为取余运算的数学结果完美契合了数组的下标范围所以只要套上% n算出来的数字就绝对不会超出数组的边界越界。2. 举个具体的例子假设我们有一个长度为n 5的数组。那么这个数组的合法下标是0, 1, 2, 3, 4。现在我们的指针比如rear在不断地1我们看看加上% 5后会发生什么当rear 0时下一步(0 1) % 5 1 % 5 1正常向后走当rear 1时下一步(1 1) % 5 2 % 5 2正常向后走当rear 2时下一步(2 1) % 5 3 % 5 3正常向后走当rear 3时下一步(3 1) % 5 4 % 5 4到达数组最后一位**【关键点】**当rear 4时下一步(4 1) % 5 5 % 5 05除以5余数为0。指针瞬间回到了开头如果继续加虽然在队列中通常是一步步走6 % 5 17 % 5 28 % 5 3...你看无论前面的数字加到多大只要你对5取余结果永远在0, 1, 2, 3, 4这个圈子里打转。总结在编程中数组越界是因为你访问了 n的下标。而% n的数学魔法就在于它把所有 n的数字都按比例折算回了0到n-1之间。就像钟表一样到了12点或者24点就又从0点开始算永远不会出现“25点”。#include stdio.h #include stdlib.h #include stdbool.h struct seqQueue { int *data; int size; int front; int rear; }; struct seqQueue *initQueue(int size) { struct seqQueue *queue malloc(sizeof(struct seqQueue)); if(queue ! NULL) { queue-data calloc(size1, sizeof(int)); if(queue-data NULL) { free(queue); return NULL; } queue-front 0; queue-rear 0; queue-size size1; } return queue; } bool isFull(struct seqQueue *queue) { return (queue-rear1)%queue-size queue-front; } bool isEmpty(struct seqQueue *queue) { return queue-front queue-rear; } //入队 bool enQueue(struct seqQueue *queue, int data) { if(isFull(queue)) { return false; } queue-data[queue-rear] data; queue-rear (queue-rear1)%queue-size; return true; } //出队 bool outQueue(struct seqQueue *queue, int *q) { if(isEmpty(queue)) { return false; } *q queue-data[queue-front]; queue-front (queue-front1)%queue-size; return true; } void show(struct seqQueue *queue) { for(int iqueue-front; i ! queue-rear; i(i1)%queue-size) { printf(%d\t, queue-data[i]); } } int main(void) { //初始化一个空的循环队列 struct seqQueue *queue initQueue(10); if(queue ! NULL) { printf(初始化队列成功\n); } int n; while(1) { if(scanf(%d,n) 1) { //入队 if(!enQueue(queue, n)) { printf(入队失败\n); continue; } } else { //清空缓冲区里的非法输入 while(getchar() ! \n); //出队 int m; if(!outQueue(queue, m)) { printf(出队失败\n); continue; } } show(queue); } }