用栈来实现队列,用队列实现栈,循环队列

用栈实现队列

整体思路是用两个栈实现一个队列,力扣上面有这个题,首先定义一个结构体包含两个栈,我们要用两个栈模拟出队列的入队,出队,返回队头元素,以及判空和释放这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);
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值