在对队列的学习时认识到了两种应用队列的场景,一是循环队列,另一个是用队列来实现栈。
- 循环队列:因为在对队列进行删除操作时会造成空间的浪费,所以引入了循环队列的思想。
循环队列中,有一个头front、一个尾rear还有一个计数器count,起始时front和rear在同一位置,count等于0。进行插入时,rear向后移动,count++;删除时front向后移动,count–。count可以用来判定队列是否满和空。
值得注意的是:在循环队列中,有效长度为***(rear - front + N) % N***
以下一道循环队列的设计题
//创建的循环队列的结构体类型变量
typedef struct {
int capacity;
int *array;
int front;
int rear;
int count;
} MyCircularQueue;
MyCircularQueue* myCircularQueueCreate(int k) {
MyCircularQueue *mq = (MyCircularQueue*)malloc(sizeof(MyCircularQueue));//在栈上创建一个指针,指向申请的变量
mq->array = (int*)malloc(sizeof(int)*k);
mq->front = mq->rear = mq->count = 0;
mq->capacity = k;
return mq;
}
//获取队尾元素
bool myCircularQueueEnQueue(MyCircularQueue* obj, int value) {
if(obj->count == obj->capacity){
return false;
}
obj->array[obj->rear++] = value;
if(obj->rear == obj->capacity){
obj->rear = 0;
}
obj->count++;
return true;
}
//删除元素
bool myCircularQueueDeQueue(MyCircularQueue* obj) {
if(obj->count == 0){
return false;
}
obj->front++;
if(obj->front == obj->capacity){
obj->front = 0;
}
obj->count--;
return true;
}
//获取队头元素
int myCircularQueueFront(MyCircularQueue* obj) {
if(obj->count == 0){
return -1;
}
return obj->array[obj->front];
}
//获取队尾元素
int myCircularQueueRear(MyCircularQueue* obj) {
if(obj->count == 0){
return -1;
}
return obj->array[(obj->rear-1 + obj->capacity) % obj->capacity];
}
//判断队列是否为空
bool myCircularQueueIsEmpty(MyCircularQueue* obj) {
if(obj->count){
return false;
}
return true;
}
//判断队列是否为满
bool myCircularQueueIsFull(MyCircularQueue* obj) {
if(obj->count == obj->capacity){
return true;
}
return false;
}
//销毁队列
void myCircularQueueFree(MyCircularQueue* obj) {
free(obj->array);
obj->front = obj->rear = obj->count = 0;
}
- 用队列实现栈。
栈的结构是先进后出,队列是先进先出。在使用队列模拟实现栈时,我们要用到两个队列q1,q2。
在进行入栈操作时,我们看哪个队列不为空就把元素插入哪个队列。
出栈时,哪个队列不为空,当它的元素大于一,就把它里边的元素出队放到另一个队列中,最后再将剩下一个元素的队列中的元素出队,这时就实现了出栈操作。
获取栈顶元素其实就是判断当前哪个队列不为空,就获取哪个队列的队尾元素,栈顶相当于队尾。
以下基于队列基础上实现的栈:
typedef struct {
Queue q1;
Queue q2;
} MyStack;
MyStack* myStackCreate() {
MyStack *ms = (MyStack*)malloc(sizeof(MyStack));
QueueInit(&ms->q1);
QueueInit(&ms->q2);
return ms;
}
//入栈
void myStackPush(MyStack* obj, int x) {
if(obj == NULL){
return;
}
//哪个队列不为空,就把元素插入哪个队列中
if(!QueueEmpty(&obj->q1)){
QueuePush(&obj->q1,x);
}
else{
QueuePush(&obj->q2,x);
}
}
//出栈
int myStackPop(MyStack* obj) {
int ret = 0;
if(!QueueEmpty(&obj->q1)){
while(QueueSize(&obj->q1)>1){
//将q1中的元素插入q2中
QueuePush(&obj->q2,QueueFront(&obj->q1));
QueuePop(&obj->q1);
}
ret = QueueFront(&obj->q1);
QueuePop(&obj->q1);
}
else{
while(QueueSize(&obj->q2)>1){
QueuePush(&obj->q1,QueueFront(&obj->q2));
QueuePop(&obj->q2);
}
ret = QueueFront(&obj->q2);
QueuePop(&obj->q2);
}
return ret;
}
//获取栈顶元素
int myStackTop(MyStack* obj) {
if(obj == NULL){
return;
}
if(!QueueEmpty(&obj->q1)){
return QueueBack(&obj->q1);
}
else{
return QueueBack(&obj->q2);
}
}
//判断栈是否为空
bool myStackEmpty(MyStack* obj) {
if(QueueEmpty(&obj->q1)&&QueueEmpty(&obj->q2)){
return true;
}
else{
return false;
}
}
void myStackFree(MyStack* obj) {
QueueDestroy(&obj->q1);
QueueDestroy(&obj->q2);
free(obj);
}