【LeetCode栈与队列#01】队列的基本操作:用栈模拟队列和用队列模拟栈

用栈实现队列

力扣题目链接(opens new window)

使用栈实现队列的下列操作:

push(x) -- 将一个元素放入队列的尾部。
pop() -- 从队列首部移除元素。
peek() -- 返回队列首部的元素。
empty() -- 返回队列是否为空。

示例:

MyQueue queue = new MyQueue();
queue.push(1);
queue.push(2);
queue.peek();  // 返回 1
queue.pop();   // 返回 1
queue.empty(); // 返回 false

说明:

  • 你只能使用标准的栈操作 -- 也就是只有 push to top, peek/pop from top, size, 和 is empty 操作是合法的。
  • 你所使用的语言也许不支持栈。你可以使用 list 或者 deque(双端队列)来模拟一个栈,只要是标准的栈操作即可。
  • 假设所有操作都是有效的 (例如,一个空的队列不会调用 pop 或者 peek 操作)

栈的基本操作

示例:

#include <stack>

//栈容器常用接口
void test01()
{
	//创建栈容器 栈容器必须符合先进后出
	stack<int> s;

	//向栈中添加元素,叫做 压栈 入栈
	s.push(10);
	s.push(20);
	s.push(30);

	while (!s.empty()) {
		//输出栈顶元素
		cout << "栈顶元素为: " << s.top() << endl;
		//弹出栈顶元素
		s.pop();
	}
	cout << "栈的大小为:" << s.size() << endl;

}

int main() {

	test01();

	system("pause");

	return 0;
}

总结:

  • 入栈 --- push
  • 出栈 --- pop
  • 返回栈顶 --- top
  • 判断栈是否为空 --- empty
  • 返回栈大小 --- size

思路

题意是要模拟一个队列的行为,用栈

队列是什么?前后都打开的一种结构,也就是说可以实现先进先出

这点用一个栈不太好还原,所以要模拟先进先出至少得使用两个 stack ,

分别为进栈(stack_in)和出栈(stack_out)

当模拟队列 push 时,我们同样只需要将数据 push 进 stack_in 即可,该动作可以直接调用官方为stack提供的 push 函数

当模拟队列 pop 时,我们要先将 stack_in 的所有数据 pop 出来再 push 进 stack_out 。

此时,之前先进入 stack_in 的数据就在 stack_out 的 top 位置了,剩下的我们只需要对 stack_out 进行 pop 操作即可模拟队列的pop。

对应的模拟动画如下:

232.用栈实现队列版本2

注意:在将 stack_in 的数据放入 stack_out 之前,必须先检查 stack_out 是否为空,不为空就直接从stack_out 往外弹数据。且往放 stack_out 数据时必须一次性全部放完,不然上述两种情况都会导致数据的顺序出错。

代码

步骤:(实现pop)

1、判断出栈是否为空

2、循环将入栈数据压入出栈

3、然后从stack_out的栈顶获取数据

class MyQueue {
public:
    //定义两个栈
    stack<int>stack_in;
    stack<int>stack_out;

    MyQueue() {

    }
    
    void push(int x) {
        stack_in.push(x);
    }
    
    int pop() {
         int tmp;
        //判断stack_out是否为空,不为空就往里面不断push数据
        if(stack_out.empty()){
            //将stack_in的全部数据push入
            while(!stack_in.empty()){
                // stack_out.push(stack_in.pop()) //错误,应该让stack_out先获取stack_in的栈顶数据,然后再pop走
                // stack_out.push(stack_in.top());//虽然在本题不会报错,但
                // stack_in.pop();//这种写法会在别的同类型的题中出错,所以统一使用下面的写法
                tmp = stack_in.top();
                stack_in.pop();
                stack_out.push(tmp);
            }
        }
        //然后从stack_out获取数据
        int res = stack_out.top();
        stack_out.pop();
        return res;

    }
    
    int peek() {//即查看栈顶数据
        int res = this->pop();//直接复用类内的pop
        //然后记得再把数据push回来
        stack_out.push(res);
        return res;

    }
    
    bool empty() {
        return stack_in.empty() && stack_out.empty();
    }
};
注意点

1、对栈进行pop操作是没有返回值的,也就是说pop之后,栈顶的数据就没了,要读数据用top读

2、能复用就复用,优雅且专业

用队列实现栈

力扣题目链接(opens new window)

使用队列实现栈的下列操作:

  • push(x) -- 元素 x 入栈
  • pop() -- 移除栈顶元素
  • top() -- 获取栈顶元素
  • empty() -- 返回栈是否为空

注意:

  • 你只能使用队列的基本操作-- 也就是 push to back, peek/pop from front, size, 和 is empty 这些操作是合法的。
  • 你所使用的语言也许不支持队列。 你可以使用 list 或者 deque(双端队列)来模拟一个队列 , 只要是标准的队列操作即可。
  • 你可以假设所有操作都是有效的(例如, 对一个空的栈不会调用 pop 或者 top 操作)

queue基本操作

示例:

#include <queue>
#include <string>
class Person
{
public:
	Person(string name, int age)
	{
		this->m_Name = name;
		this->m_Age = age;
	}

	string m_Name;
	int m_Age;
};

void test01() {

	//创建队列
	queue<Person> q;

	//准备数据
	Person p1("唐僧", 30);
	Person p2("孙悟空", 1000);
	Person p3("猪八戒", 900);
	Person p4("沙僧", 800);

	//向队列中添加元素  入队操作
	q.push(p1);
	q.push(p2);
	q.push(p3);
	q.push(p4);

	//队列不提供迭代器,更不支持随机访问	
	while (!q.empty()) {
		//输出队头元素
		cout << "队头元素-- 姓名: " << q.front().m_Name 
              << " 年龄: "<< q.front().m_Age << endl;
        
		cout << "队尾元素-- 姓名: " << q.back().m_Name  
              << " 年龄: " << q.back().m_Age << endl;
        
		cout << endl;
		//弹出队头元素
		q.pop();
	}

	cout << "队列大小为:" << q.size() << endl;
}

int main() {

	test01();

	system("pause");

	return 0;
}

总结:

  • 入队 --- push
  • 出队 --- pop
  • 返回队头元素 --- front
  • 返回队尾元素 --- back
  • 判断队是否为空 --- empty
  • 返回队列大小 --- size

思路

用一个队列就可以模拟栈的行为

一个队列在模拟栈弹出元素的时候只要将队列头部的元素(除了最后一个元素外) 重新添加到队列尾部,此时再去弹出元素就是栈的顺序了。

代码

步骤:(实现pop)

1、获取队列长度qLen

2、循环,只需循环qLen-1的部分,最后一个元素不用动。不断获取队头数据再加入队尾,然后pop调当前数据

3、循环结束后,现在队中元素的顺序就颠倒了(与栈顺序一致),接下来就从队头拿数据就行,

class MyStack {
public:
    //创建队列
    queue<int> q;

    MyStack() {

    }
    
    void push(int x) {
        q.push(x);
    }
    
    int pop() {
        //获取队列长度
        int qLen = q.size();
        //需要循环的部分不包含最后一个数
        qLen--;
        while(qLen--){
            //将队头的数据push到队尾
            q.push(q.front());
            //弹出当前队头数据
            q.pop();
        }
        //已获得需要的数据顺序
        //一个一个获取即可
        int res = q.front();
        q.pop();
        return res;
    }
    
    int top() {
        //在栈里面的第一个元素,其实就是队列的最后一个元素,用back方法可以获取到
        return q.back();
    }
    
    bool empty() {
        return q.empty();
    }
};

TBD

posted @ 2023-02-14 21:05  dayceng  阅读(64)  评论(0编辑  收藏  举报