每日一题(设计循环队列)
622. 设计循环队列 - 力扣(LeetCode)
1.题意解读
本题只能为队列开辟k个单位空间,并且只能利用这几个空间进行数据的存储。
思路:本题使用数组来实现队列是比较方便的,首先定义两个变量:front和rear变量。分别用于记录队头和队尾。一开始初始化时让front和rear都指向数组的第一个位置,存储数据时,按着下图的方式,向rear下标处存储数据,存储成功之后rear自加1,也就是意味着rear始终指向的当前队尾元素的下一个位置。
分析:假设k的值是5,那么本来应该就是开辟5个空间。但是我用的这种方法需要多开辟一个单位的空间。为什么呢?假若我们开辟的是5的单位的空间,那么当存满了k个数据之后,此时的rear和front就都指向了数组中的第一个元素。那么请仔细想想,在初始化的时候我们也将rear和front也初始化为了0,也指向了数组中的第一个元素。那么在这两种情况下,front和rear都指向了数组的第一个元素,但是队列中的元素个数却是大不相同,无法将队列为满和队列为空进行分开。为了避免这种问题的发生,这里多开辟一个空间,当rear下标的下一个位置是front时,此时队列中存储了k个元素,也就说明了队列已满,那么同时判断队列为空就很方便了。只要rear与front相等时,队列就为空。
删除队头元素:删除队头的元素就只需要将front++即可。
注意:
- 当遇到了非常规情况时:rear到了队尾需要循环到队头时,则只需要执行语句
rear++;rear %= k+1;
这两条语句即可。针对front到达队尾需要到达队头的情况也同样适用的。- 当需要获取队尾的元素时,实际上获取的是rear的前一个下标处的值,需要访问rear-1下标处的值,但是假若此时的rear的值是0,那么此时需要特判以下,假如rear的值是0时,直接访问k下标处的值即可。rear的值不为0时,只需要正常访问rear-1下标处的元素即可。
代码实现:
typedef struct {int* a;int front;int rear;int k;
} MyCircularQueue;MyCircularQueue* myCircularQueueCreate(int k) {
MyCircularQueue* obj = (MyCircularQueue*)malloc(sizeof(MyCircularQueue));obj->a = (int*)malloc(sizeof(int)*(k+1));obj->front = 0;obj->rear = 0;obj->k = k;return obj;
}bool myCircularQueueIsEmpty(MyCircularQueue* obj) {assert(obj);return ((obj->rear)==(obj->front));
}bool myCircularQueueIsFull(MyCircularQueue* obj) {assert(obj);return (((obj->rear+1)%(obj->k+1))==(obj->front));
}bool myCircularQueueEnQueue(MyCircularQueue* obj, int value) {assert(obj);if(!myCircularQueueIsFull(obj))//未满{obj->a[obj->rear] = value;obj->rear++;obj->rear %= (obj->k+1);return true;}return false;
}bool myCircularQueueDeQueue(MyCircularQueue* obj) {assert(obj);if(!myCircularQueueIsEmpty(obj))//非空{obj->front++;obj->front %=obj->k+1;return true;}return false;
}int myCircularQueueFront(MyCircularQueue* obj) {assert(obj);if(myCircularQueueIsEmpty(obj)){return -1;}return obj->a[obj->front];
}int myCircularQueueRear(MyCircularQueue* obj) {assert(obj);if(myCircularQueueIsEmpty(obj)){return -1;}if(obj->rear == 0)return obj->a[obj->k];else{return obj->a[obj->rear-1];}
}void myCircularQueueFree(MyCircularQueue* obj) {assert(obj);free(obj->a);free(obj);obj=NULL;
}
完结
设计循环队列的分析就到这里啦,若有不足,欢迎评论区指正,下期见!