用栈实现队列
整体思路是用两个栈实现一个队列,力扣上面有这个题,首先定义一个结构体包含两个栈,我们要用两个栈模拟出队列的入队,出队,返回队头元素,以及判空和释放这5个接口。
两个栈,其中一个用来模仿队列,另外一个栈用来做中转,入队的时候就是正常的压栈操作,和栈的操作没有区别,假设我们采用st1作为队列,在模仿队列的出队过程中,我们的思路是先将所有的st1中的元素从队头入栈st2,入栈一个出栈一个,直到st1栈只剩下一个元素,这个元素就是我们要出栈的元素,把这个出栈之后还不算完,我们还要把st2栈中的元素入栈st1,入栈一个出栈一个,直到st2栈中的元素全部出栈,此时才算结束,返回要出栈的元素。
返回队头元素和出队操作类似只是st1栈底的元素并不出栈(也就是队头元素),入栈st2一个出栈st1一个,知道st1栈只剩下一个元素,把这个元素记录下来,然后返回。
typedef struct {
ST st1;
ST st2;
} MyQueue;
MyQueue* myQueueCreate() {
MyQueue* obj=(MyQueue*)malloc(sizeof(MyQueue));
StackInit(&obj->st1);
StackInit(&obj->st2);
return obj;
}
void myQueuePush(MyQueue* obj, int x) {
assert(obj);
StackPush(&obj->st1,x);
}
int myQueuePop(MyQueue* obj) {
assert(obj);
while(StackSize(&obj->st1)>1)
{
StackPush(&obj->st2,StackTop(&obj->st1));
StackPop(&obj->st1);
}
int top=StackTop(&obj->st1);
StackPop(&obj->st1);
while(!StackEmpty(&obj->st2))
{
StackPush(&obj->st1,StackTop(&obj->st2));
StackPop(&obj->st2);
}
return top;
}
int myQueuePeek(MyQueue* obj) {
assert(obj);
while(StackSize(&obj->st1)>1)
{
StackPush(&obj->st2,StackTop(&obj->st1));
StackPop(&obj->st1);
}
int top=StackTop(&obj->st1);
while(!StackEmpty(&obj->st2))
{
StackPush(&obj->st1,StackTop(&obj->st2));
StackPop(&obj->st2);
}
return top;
}
bool myQueueEmpty(MyQueue* obj) {
return StackEmpty(&obj->st1);
}
void myQueueFree(MyQueue* obj) {
free(obj);
}
用队列实现栈
用队列实现栈,思路是两个队列来模仿,要模仿栈的后入先出操作,我们可以选定不固定的一个作为栈(可以交替当栈),我们拥有两个队列q1,q2,当我们要出栈刚刚入队的元素的时候,我们只需要将该元素前面的所有元素出队,然后进入另外一个队,然后这个元素出队我们就模仿出了栈的出栈,下一次就选用另外一个队列当栈。代码如下
typedef struct {
Queue q1;
Queue q2;
} MyStack;
MyStack* myStackCreate() {
MyStack* obj=(MyStack*)malloc(sizeof(MyStack));
QueueInit(&obj->q1);
QueueInit(&obj->q2);
return obj;
}
void myStackPush(MyStack* obj, int x)
{
if(!QueueEmpty(&obj->q1))
{
QueuePush(&obj->q1,x);
}
else
{
QueuePush(&obj->q2,x);
}
}
int myStackPop(MyStack* obj)
{
Queue* empty=&obj->q1;
Queue* nonempty=&obj->q2;
if(!QueueEmpty(&obj->q1))
{
empty=&obj->q2;
nonempty=&obj->q1;
}
while(QueueSize(nonempty)>1)
{
QueuePush(empty,QueueFront(nonempty));
QueuePop(nonempty);
}
int top=QueueFront(nonempty);
QueuePop(nonempty);
return top;
}
int myStackTop(MyStack* obj) {
if(!QueueEmpty(&obj->q1))
return QueueBack(&obj->q1);
else
return QueueBack(&obj->q2);
}
bool myStackEmpty(MyStack* obj) {
return QueueEmpty(&obj->q1)&&QueueEmpty(&obj->q2);
}
void myStackFree(MyStack* obj)
{
if(!QueueEmpty(&obj->q1))
{
QueueDestroy(&obj->q1);
}
else
{
QueueDestroy(&obj->q2);
}
free(obj);
}
循环队列的实现
采用一个固定大小的数组来当作循环队列,数组的大小为N,最多能存放的数据为N-1,这么做的原因是让rear==front的时候作为队空的条件,避免和队满的条件产生二义性,当(rear+k)%(k+1)==front的时候队满。
代码如下:
typedef struct
{
int* a;
int front;
int rear;
int k;
} MyCircularQueue;
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);
}
MyCircularQueue* myCircularQueueCreate(int k)
{
MyCircularQueue* obj=(MyCircularQueue*)malloc(sizeof(MyCircularQueue));
obj->a=(int*)malloc(sizeof(int)*(k+1));
obj->front=obj->rear=0;
obj->k=k;
return obj;
}
bool myCircularQueueEnQueue(MyCircularQueue* obj, int value)
{
assert(obj);
if(myCircularQueueIsFull(obj))
{
return false;
}
obj->a[obj->rear++]=value;
obj->rear%=(obj->k+1);
return true;
}
bool myCircularQueueDeQueue(MyCircularQueue* obj)
{
assert(obj);
if(myCircularQueueIsEmpty(obj))
{
return false;
}
obj->front++;
obj->front%=(obj->k+1);
return true;
}
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;
}
return obj->a[(obj->rear+obj->k)%(obj->k+1)];
}
void myCircularQueueFree(MyCircularQueue* obj)
{
free(obj->a);
free(obj);
}