🍄(3)队列的应用:
LeetCode——225. 用队列实现栈
题目描述:
思路:
每次入队数据都需要从不为空的队列进,这样可以保证
Push:进栈,对应到两个队列的操作就是,入不为空的队列。
Top:得到栈顶数据,对应到两个队列的操作就是,得到两个队列中不为空的队列的队尾数据。
Pop:删除栈顶数据,对应的两个队列的操作就是,删除不为空队列的队尾数据元素,但是由于队列结构的原因,要想删除队尾数据,就要先删除队尾前面的数据,所以我们可以先将队尾前面的数据放到另外一个空队列,再将队尾数据删除。
Empty:判断栈是否为空,对应的两个队列的操作就是,只有两个队列都已经没有数据时,栈才为空。
代码:
//队列结构 typedef int QUDateType; typedef struct QueueNode { QUDateType date; struct QueueNode* next; }QueueNode; typedef struct Queue { QueueNode* head; QueueNode* tail; int size; }Queue; void QueueInit(Queue* pque) { assert(pque); pque->head = NULL; pque->tail = NULL; pque->size = 0; } //进队列 void QueuePush(Queue* pque,QUDateType x) { assert(pque); QueueNode* newnode = (QueueNode*)malloc(sizeof(QueueNode)); if (newnode == NULL) { perror("malloc"); exit(-1); } newnode->date = x; newnode->next = NULL; if (pque->head == NULL) { pque->head = pque->tail = newnode; } else { pque->tail->next = newnode; pque->tail = newnode; } pque->size++; } //队列为空 bool QueueEmpty(Queue* pque) { assert(pque); return pque->head == NULL && pque->tail == NULL; } //得到对头数据 QUDateType QueueFront(Queue*pque) { assert(pque); assert(!QueueEmpty(pque)); return pque->head->date; } //得到队尾数据 QUDateType QueueBack(Queue* pque) { assert(pque); assert(!QueueEmpty(pque)); return pque->tail->date; } //队列数据个数 int QueueSize(Queue* pque) { assert(pque); return pque->size; } //删除队头数据 void QueuePop(Queue* pque) { assert(pque); assert(!QueueEmpty(pque)); //队列中只有一个数据的时候 if (pque->head->next == NULL) { free(pque->head); pque->tail = pque->head = NULL; } else { QueueNode* popnode = pque->head; pque->head = pque->head->next; free(popnode); } pque->size--; } //队列销毁 void QueueDestroy(Queue* pque) { assert(pque); QueueNode* cur = pque->head; while (cur) { QueueNode* nextnode = cur->next; free(cur); cur = nextnode; } pque->head = pque->tail = NULL; } //封装两个队列 typedef struct { Queue q1; Queue q2; } MyStack; //创建栈 MyStack* myStackCreate() { MyStack*Q=(MyStack*)malloc(sizeof(MyStack)); QueueInit(&Q->q1); QueueInit(&Q->q2); return Q; } //将元素 x 压入栈顶。 void myStackPush(MyStack* obj, int x) { //找到空队列与非空队列 QueueNode*empty=&obj->q1; QueueNode*noempty=&obj->q2; if(!QueueEmpty(&obj->q1)) { empty=&obj->q2; noempty=&obj->q1; } //将数据入空队列 QueuePush(noempty,x); } //删除栈顶数据 int myStackPop(MyStack* obj) { assert(obj); //找到空队列与非空队列 QueueNode*empty=&obj->q1; QueueNode*noempty=&obj->q2; if(!QueueEmpty(&obj->q1)) { empty=&obj->q2; noempty=&obj->q1; } //将非空队列只留一个数据,其他的全部出队到空队列 while(QueueSize(noempty)>1) { QueuePush(empty,QueueFront(noempty)); QueuePop(noempty); } //返回非空队列的最后一个数据 int ret=QueueFront(noempty); QueuePop(noempty); return ret; } //返回栈顶数据 int myStackTop(MyStack* obj) { assert(obj); QueueNode*empty=&obj->q1; QueueNode*noempty=&obj->q2; if(!QueueEmpty(&obj->q1)) { empty=&obj->q2; noempty=&obj->q1; } return QueueBack(noempty); } //栈判空 bool myStackEmpty(MyStack* obj) { assert(obj); return QueueEmpty(&obj->q1)&&QueueEmpty(&obj->q2); } //销毁栈 void myStackFree(MyStack* obj) { assert(obj); QueueDestroy(&obj->q1); QueueDestroy(&obj->q2); free(obj); }
测试:
2.LeetCode——622. 设计循环队列
题目描述:
思路:在设计循环队列的时候,我们可以使用数组,或者链表都是可以的,这里我们就使用数组来实现循环队列。
1.MyCircularQueue(结构)
typedef struct { int *date; //最后一个数据的下一个坐标 int tail; //头指针 int head; 循环队列的容量 int k; } MyCircularQueue;
2.MyCircularQueue(k)(创建)
在设计循环队列的时候,我们设计队列的容量时多开一个容量,目的是为了更好的分清队空和队满,队空和队满的时候,头尾坐标都会指在同一位置上。
MyCircularQueue* myCircularQueueCreate(int k) { MyCircularQueue*Q=(MyCircularQueue*)malloc(sizeof(MyCircularQueue)); Q->date=(int *)malloc(sizeof(int)*(k+1)); Q->tail=0; Q->head=0; Q->k=k; return Q; }
3.myCircularQueueEnQueue(入队)
bool myCircularQueueEnQueue(MyCircularQueue* obj, int value) { //先判断队列是否已经满了 if(myCircularQueueIsFull(obj)) { return false; } //断言判断队列结构 assert(obj); //在队尾出数据 obj->date[obj->tail++]=value; //当数据尾部已经在数组的最后了,此时在进入数据后, //数据尾巴下标时刻保持在数据尾部的后一个下标的, //就要回到数组的头部位置。 if(obj->tail==(obj->k)+1) { obj->tail=0; } return true; }
4.Front
(获取对头数据)
int myCircularQueueFront(MyCircularQueue* obj) { assert(obj); //队列不为空,才可以获得数据 if(myCircularQueueIsEmpty(obj)) { return -1; } return obj->date[obj->head]; }
5.deQueue(删除对头数据)
bool myCircularQueueDeQueue(MyCircularQueue* obj) { assert(obj); //队列不能为空 if(myCircularQueueIsEmpty(obj)) { return false; } //如果head不在数组的尾部,直接head++ obj->head++; //如果head,在数组的最后一个位置,此时head++以后需要循环到数组第一个位置 if(obj->head==obj->k+1) { obj->head=0; } return true; }
6.Rear(获得队尾数据)
int myCircularQueueRear(MyCircularQueue* obj) { assert(obj); //首先队列不能为空 if(myCircularQueueIsEmpty(obj)) { return -1; } //当数据尾在数组开头处,最后一个数据在数组的尾部 //此时k就是数组的最后一个数据的下标 if(obj->tail-1<0) { return obj->date[obj->k]; } //如果数据尾部在数组中间或者是在数组尾部,数据尾部就是date[tail-1]. return obj->date[obj->tail-1]; }
7.isEmpty(判断队列是否为空)
bool myCircularQueueIsEmpty(MyCircularQueue* obj) { assert(obj); //头尾相等就是空。 return obj->tail==obj->head; }
8.isFull(判断队列是否满)
bool myCircularQueueIsFull(MyCircularQueue* obj) { assert(obj); //当tail在数组的最后一个位置时,head在数组第一个位置。 //tail不在数据的最后。 return (obj->tail+1)%(obj->k+1)==obj->head; }
9. 销毁队列
void myCircularQueueFree(MyCircularQueue* obj) { assert(obj); free(obj->date); free(obj); }
代码:
typedef struct { int *date; int tail; int head; int k; } MyCircularQueue; bool myCircularQueueIsEmpty(MyCircularQueue* obj); bool myCircularQueueIsFull(MyCircularQueue* obj); MyCircularQueue* myCircularQueueCreate(int k) { MyCircularQueue*Q=(MyCircularQueue*)malloc(sizeof(MyCircularQueue)); Q->date=(int *)malloc(sizeof(int)*(k+1)); Q->tail=0; Q->head=0; Q->k=k; return Q; } bool myCircularQueueEnQueue(MyCircularQueue* obj, int value) { if(myCircularQueueIsFull(obj)) { return false; } assert(obj); obj->date[obj->tail++]=value; if(obj->tail==(obj->k)+1) { obj->tail=0; } return true; } bool myCircularQueueDeQueue(MyCircularQueue* obj) { assert(obj); if(myCircularQueueIsEmpty(obj)) { return false; } obj->head++; if(obj->head==obj->k+1) { obj->head=0; } return true; } int myCircularQueueFront(MyCircularQueue* obj) { assert(obj); if(myCircularQueueIsEmpty(obj)) { return -1; } return obj->date[obj->head]; } int myCircularQueueRear(MyCircularQueue* obj) { assert(obj); if(myCircularQueueIsEmpty(obj)) { return -1; } if(obj->tail-1<0) { return obj->date[obj->k]; } return obj->date[obj->tail-1]; } bool myCircularQueueIsEmpty(MyCircularQueue* obj) { assert(obj); return obj->tail==obj->head; } bool myCircularQueueIsFull(MyCircularQueue* obj) { assert(obj); return (obj->tail+1)%(obj->k+1)==obj->head; } void myCircularQueueFree(MyCircularQueue* obj) { assert(obj); free(obj->date); free(obj); }
测试:
🍂最后
要想改变我们的人生,第一步就是要改变我们的心态。只要心态是正确的,我们的世界就会的光明的。