刷爆leetcode第八期 0019

简介: 刷爆leetcode第八期 0019

题目编号0019 用两个栈实现队列


请你仅使用两个栈实现先入先出队列。队列应当支持一般队列支持的所有操作(push、pop、peek、empty):


实现 MyQueue 类:


void push(int x) 将元素 x 推到队列的末尾

int pop() 从队列的开头移除并返回元素

int peek() 返回队列开头的元素

boolean empty() 如果队列为空,返回 true ;否则,返回 false

说明:


你 只能 使用标准的栈操作 —— 也就是只有 push to top, peek/pop from top, size, 和 is empty 操作是合法的。

你所使用的语言也许不支持栈。你可以使用 list 或者 deque(双端队列)来模拟一个栈,只要是标准的栈操作即可。


来源:力扣(LeetCode)

链接:https://leetcode.cn/problems/implement-queue-using-stacks


整体分析


我们先来分析题目 跟我们昨天刷的题目区别不大


先来画图看看两个栈是什么样子的

09b3de2ece0546c19b865d4f1346b37f.png

这里进栈的顺序分别是 1 2 3 4 5


我们将这些数据迁移到另一个栈之中试试

35ba7c57ef0a49848f876bdeabaf8e3a.png



我们可以发现 这里的数据竟然倒过来了!


那么我们取数据的顺序就变成了


1 2 3 4 5


我们发现这就刚好是跟队列删取数据的顺序一样了


所以说我们可以这样子设计这两个栈

6ff21e9d151e41379627df552a7c714f.png


接下来我们知道了这两个栈的基本结构了 我们来做题目试试


我们先来看第一个


第一步 初始化


我们先来看 我们创建的结构体是什么样子的


typedef struct
{
    ST tpush;
    ST tpop;
} MyQueue;


typedef struct Stack
{
  StackType* a;  //储存数据的大小
  int Top;       //栈顶
  int Capacity;  //数组容量大小 
}ST;


这里是两个结构体的套用


MyQueue myQueue = new MyQueue();


MyQueue* myQueueCreate() 
{
    MyQueue* obj = (MyQueue* myQueue)malloc(sizeof(MyQueue));
    StackInit(&obj->tpush);
    StackInit(&obj->tpop);
    return obj;
}


要求我们这样子 返回一个指针


那么这一步很简单 我们使用动态内存开辟一块空间就好了


之后返回一个指针指向这块空间


第二步 插入


void myQueuePush(MyQueue* obj, int x) 
{
}


这一步我们也讲的很明白了 插入往第一个里面插


所以说我们有以下代码


void myQueuePush(MyQueue* obj, int x) 
{
}
1
2
3
这一步我们也讲的很明白了 插入往第一个里面插
所以说我们有以下代码


直接这样子就可以了


第三步 删除


再来上图

0b5a64f9a72a4acb9dd7364341e913de.png

90dfca5ef4f34f19b720290e328d5171.png



我们一边取第一个栈的头元素放置到第二个栈中


一边删除第一个栈中的元素


知道第一个栈为空为止


代码表示如下


int myQueuePop(MyQueue* obj) 
{
    if(StackEmpty(&obj->tpop))
    {
        while(!StackEmpty(&obj->tpush))
        {
            StackPush(&obj->tpop,StackTop(&obj->tpush));
            StackPop(&obj->tpush);
        }
    }
    int front = StackTop(&obj->tpop);
    StackPop(&obj->tpop);
    return front;
}


第四步 返回头元素


这个很简单和删除差不多


先将所有的元素移动到第二个栈当中 返回栈的头值就可以


直接上代码


int myQueuePeek(MyQueue* obj) 
{
        if(StackEmpty(&obj->tpop))
    {
        while(!StackEmpty(&obj->tpush))
        {
            StackPush(&obj->tpop,StackTop(&obj->tpush));
            StackPop(&obj->tpush);
        }
    }
    return StackTop(&obj->tpop);
}


第五步 判断是否为空


这一步也很简单


两个都为空就是空了


直接上代码


bool myQueueEmpty(MyQueue* obj) 
{
    return StackEmpty(&obj->tpush) && StackEmpty(&obj->tpop);
}


第六步 释放内存


这一步要注意了!!!


我们需要先释放开辟的两个栈的内存


之后再释放我们开辟的队列的内存


代码表示如下


void myQueueFree(MyQueue* obj) 
{
    StackDestroy(&obj->tpush);
    StackDestroy(&obj->tpop);
    free(obj);
    obj=NULL;
}


代码运行结果如下


810d89ef1ade4c1c9c39c3ced3b5e38b.png


总结


并没有什么特别的难点


写的也比较顺利


收获应该是巩固了队列和栈的基本知识


源代码


#include<stdio.h>
#include<stdlib.h>
#include<stdbool.h>
#include<math.h>
#include<assert.h>
typedef char StackType;
typedef struct Stack
{
  StackType* a;  //储存数据的大小
  int Top;       //栈顶
  int Capacity;  //数组容量大小 
}ST;
void StackInit(ST* p);
void StackPush(ST* p, StackType x);
void StackPop(ST* p);
int StackSize(ST* p);
StackType StackTop(ST* p);
// 判断栈是否为空 如果为空 返回True 如果为假 返回False
bool StackEmpty(ST* p);
void StackDestroy(ST* p);
void StackInit(ST* p)
{
  assert(p);
  p->a = NULL;
  p->Top = 0;
  p->Capacity = 0;
}
void StackPush(ST* p, StackType x)
{
  assert(p);
  if (p->Top==p->Capacity)
  {
    int NewCapacity = p->Capacity == 0 ? 4: p->Capacity * 2;
    StackType* Tmp = realloc(p->a,NewCapacity*sizeof(StackType));
    if (Tmp==NULL)
    {
      perror("StackPush realloc");
    }
    else
    {
      p->Capacity = NewCapacity;
      p->a = Tmp;
    }
  }
  p->a[p->Top] = x;
  p->Top++;
}
void StackPop(ST* p)
{
  assert(p);
  assert(p->Top > 0);
  p->Top--;
}
void StackPrint(ST* p)
{
  assert(p);
  while (p->Top>0)
  {
    printf("%d  ", p->a[p->Top - 1]);
    StackPop(p);
  }
}
int StackSize(ST* p)
{
  assert(p);
  return p->Top;
}
bool StackEmpty(ST* p)
{
  assert(p);
  return p->Top==0;
}
void StackDestroy(ST* p)
{
  assert(p);
  free(p->a);
  p->a == NULL;
  p->Capacity = 0;
  p->Top = 0;
}
StackType StackTop (ST* p)
{
  assert(p);
  assert(p->Top > 0);
  return p->a[p->Top - 1];
}
typedef struct
{
    ST tpush;
    ST tpop;
} MyQueue;
MyQueue* myQueueCreate() 
{
    MyQueue* obj = (MyQueue*)malloc(sizeof(MyQueue));
    StackInit(&obj->tpush);
    StackInit(&obj->tpop);
    return obj;
}
void myQueuePush(MyQueue* obj, int x) 
{  
    //要求传递的参数是指针 所以说要用数组来接受
    StackPush(&obj->tpush,x);
}
int myQueuePop(MyQueue* obj) 
{
    if(StackEmpty(&obj->tpop))
    {
        while(!StackEmpty(&obj->tpush))
        {
            StackPush(&obj->tpop,StackTop(&obj->tpush));
            StackPop(&obj->tpush);
        }
    }
    int front = StackTop(&obj->tpop);
    StackPop(&obj->tpop);
    return front;
}
int myQueuePeek(MyQueue* obj) 
{
        if(StackEmpty(&obj->tpop))
    {
        while(!StackEmpty(&obj->tpush))
        {
            StackPush(&obj->tpop,StackTop(&obj->tpush));
            StackPop(&obj->tpush);
        }
    }
    return StackTop(&obj->tpop);
}
bool myQueueEmpty(MyQueue* obj) 
{
    return StackEmpty(&obj->tpush) && StackEmpty(&obj->tpop);
}
void myQueueFree(MyQueue* obj) 
{
    StackDestroy(&obj->tpush);
    StackDestroy(&obj->tpop);
    free(obj);
    obj=NULL;
}
/**
 * Your MyQueue struct will be instantiated and called as such:
 * MyQueue* obj = myQueueCreate();
 * myQueuePush(obj, x);
 * int param_2 = myQueuePop(obj);
 * int param_3 = myQueuePeek(obj);
 * bool param_4 = myQueueEmpty(obj);
 * myQueueFree(obj);
*/
相关文章
|
5月前
刷爆leetcode第一期
刷爆leetcode第一期
23 1
|
5月前
刷爆leetcode第八期
刷爆leetcode第八期
16 0
|
5月前
刷爆leetcode第七期
刷爆leetcode第七期
21 0
|
5月前
刷爆leetcode第六期
刷爆leetcode第六期
20 0
|
5月前
|
测试技术 C语言
刷爆leetcode第五期
刷爆leetcode第五期
23 0
|
5月前
|
索引
刷爆leetcode第四期
刷爆leetcode第四期
19 0
|
5月前
|
索引
刷爆leetcode第三期
刷爆leetcode第三期
25 0
|
5月前
刷爆leetcode第二期
刷爆leetcode第二期
27 0
|
算法 测试技术
刷爆 LeetCode 双周赛 100,单方面宣布第一题最难
上周末是 LeetCode 第 100 场双周赛,你参加了吗?这场周赛整体没有 Hard 题,但是也没有 Easy 题。第一题国服前百名里超过一半人 wa,很少见。
124 0
刷爆leetcode第七期 0018
刷爆leetcode第七期 0018
108 0
刷爆leetcode第七期 0018