算法题-栈与队列

1.栈与队列理论基础

队列是先进先出,栈是先进后出
在这里插入图片描述

1.1栈

栈是以底层容器来完成所有的工作,对外提供统一的接口,底层容易使可插拔的(可以控制使用哪种底层容易来实现栈的功能)
所以STL中栈往往不被归类为容器,而被归类为container adapter(容器适配器)。
在这里插入图片描述

1.1.1C++stack(栈)

在计算机科学领域,我们致力于各种程序。他们每个人都有自己的域和实用程序。根据程序创建的目的和环境,我们有大量数据结构可供选择。其中之一是“堆栈”。在讨论这种数据类型之前,让我们看一下它的语法。

  • 语法
template<class T, class Container = deque<T> > class stack;

这种数据结构使用LIFO技术,其中LIFO表示后进先出。首先插入的元素将在末尾提取,以此类推。有一个名为“top”的元素,它是位于最上面位置的元素。所有插入和删除操作都是在堆栈的顶部元素本身进行的。
应用区域中的堆栈暗示为容器适配器。
容器应支持下列操作列表

在这里插入图片描述

  • 成员类型
    在这里插入图片描述

  • 函数
    借助函数,可以在编程领域中使用对象或变量。堆栈提供了大量可以在程序中使用或嵌入的函数。相同的列表如下:
    函数

1.2队列

1.2.1C++queue(队列)

此数据结构适用于FIFO技术,其中FIFO表示先进先出。首先插入的元素将首先被提取,依此类推。有一个称为“前”的元素,它是位于最前位置或位于第一个位置的元素,也有一个名为“后”的元素,它是位于最后位置的元素。在普通队列中,元素的插入在尾部,而删除则从前面开始。

函数

在这里插入图片描述

1.2.2C++优先队列(priority_queue)

C ++中的优先队列是STL中的派生容器,它仅考虑最高优先级元素。队列遵循FIFO策略,而优先队列根据优先级弹出元素,即,优先级最高的元素首先弹出。
它在某些方面类似于普通队列,但在以下方面有所不同:
在优先队列中,队列中的每个元素都与某个优先级相关联,但是优先级在队列数据结构中不存在。
优先队列中具有最高优先级的元素将被首先删除,而队列遵循FIFO(先进先出)策略,这意味着先插入的元素将被首先删除。
如果存在多个具有相同优先级的元素,则将考虑该元素在队列中的顺序。
优先队列是一种特殊的队列,这种队列会自动的把队列里的数排序(默认从大到小,使用“<”判断),而且还可以把数按照特定的方法排列!(包括结构体和重载"<")
在这里插入图片描述
在上图中,我们通过使用push()函数插入了元素,并且插入操作与普通队列相同。但是,当我们使用pop()函数从队列中删除元素时,优先级最高的元素将首先被删除。
例:

#include <iostream>
#include <queue>
#include <vector>
#include <functional>

using namespace std;

int main() {
    // 创建一个优先队列,默认是最大堆
    priority_queue<int> pq;

    // 插入元素
    pq.push(10);
    pq.push(30);
    pq.push(20);
    pq.push(5);
    pq.push(1);

    // 输出并移除优先队列中的元素
    cout << "优先队列中的元素按优先级顺序(大顶堆)出队:" << endl;
    while (!pq.empty()) {
        cout << pq.top() << " ";  // 输出队列顶部元素
        pq.pop();                 // 移除顶部元素
    }
    cout << endl;

    // 创建一个优先队列(最小堆)
    priority_queue<int, vector<int>, greater<int>> minHeap;

    // 插入元素
    minHeap.push(10);
    minHeap.push(30);
    minHeap.push(20);
    minHeap.push(5);
    minHeap.push(1);

    // 输出并移除优先队列中的元素
    cout << "优先队列中的元素按优先级顺序(小顶堆)出队:" << endl;
    while (!minHeap.empty()) {
        cout << minHeap.top() << " ";
        minHeap.pop();
    }
    cout << endl;

    return 0;
}

输出:

优先队列中的元素按优先级顺序(大顶堆)出队:
30 20 10 5 1
优先队列中的元素按优先级顺序(小顶堆)出队:
1 5 10 20 30
函数

在这里插入图片描述

1.2.3C++deque(双端队列)

双端队列即可以从前端或后端的两段进行插入和删除
在这里插入图片描述

函数

在这里插入图片描述

2.相关算法题

2.1用栈实现队列(*)

题目

class MyQueue {
public:
    stack<int> st_in;
    stack<int> st_out;
    //初始化你的数据结构
    MyQueue() 
    {

    }
    
    void push(int x) 
    {
        st_in.push(x);

    }
    
    int pop() 
    {
        //当st_out为空的时候,再从st_int里导入数据
        if(st_out.empty())
        {
            while(!st_in.empty())
            {
                st_out.push(st_in.top());
                st_in.pop();
            }
        }
        int result = st_out.top();
        st_out.pop();
        return result;
    }
   
    int peek() 
    {
        int res = this->pop();//直接使用已有的pop函数
        //this是一个隐含指针,指向调用成员变量和成员函数
        st_out.push(res); //因为pop函数弹出了元素res,所以再添加回去
        return res;
    }
    
    bool empty() 
    {
        return st_in.empty() && st_out.empty();

    }
};

这里的this是一个隐含的指针,指向调用成员函数的对象本身,它可以在类的成员函数内部使用,用于访问该对象的成员变量和成员函数

2.2用队列实现栈(*)

题目

class MyStack 
{
public:
    queue<int> que1;
    queue<int> que2; //辅助队列,用来备份
    MyStack() 
    {

    }
    
    void push(int x) 
    {
        que1.push(x);

    }
    
    int pop() 
    {
        int size = que1.size();
        size--;
        while(size--)
        {
            que2.push(que1.front());
            que1.pop();
        }

        int result = que1.front();
        que1.pop();
        que1 = que2; //再将que2值赋给que1
        while(!que2.empty()) //清空que2
        {
            que2.pop();
        }
        return result;
    }
    
    int top() 
    {
        return que1.back();

    }
    
    bool empty() 
    {
        return que1.empty();
    }
};

2.3有效的括号

题目

class Solution 
{
public:
    bool isValid(string s) 
    {
       unordered_map<char, char> mp = {{')', '('}, {']', '['}, {'}', '{'}};
       stack<char> st;
       for(int i = 0; i < s.size(); i++)
       {
            if (s[i] == '{' || s[i] == '[' || s[i] == '(')
            {
                st.push(s[i]);
            }
            else
            {
                if (!st.empty())
                {
                    char ch = st.top();
                    if (ch != mp[s[i]])
                    {
                        return false;
                    }
                    else
                    {
                        st.pop();
                    }
                } 
                else
                {
                    return false;
                }               
            }

       }
       return st.empty();

    }
};

2.4删除字符串中的所有相邻重复项

题目

class Solution 
{
public:
    string removeDuplicates(string s) 
    {
        stack<char> st;
        for (char ch : s)
        {
            if (st.empty())
            {
                st.push(ch);
            }
            else
            {
                if (st.top() == ch)
                {
                    st.pop();
                }
                else
                {
                    st.push(ch);
                }
            }
        }
        string res;
        while(!st.empty())
        {
            res += st.top();
            st.pop();
        }
        reverse(res.begin(), res.end());  
        return res;  
    }
};

2.5 逆波兰表达式求值

题目

class Solution
{
public:
    int evalRPN(vector<string>& tokens) 
    {
        unordered_set<string> oper_set = {"+", "-", "*", "/"};
        stack<int> st;
        for (int i = 0; i < tokens.size(); i++)
        {
            if(oper_set.find(tokens[i]) == oper_set.end())
            {
                st.push(stoi(tokens[i]));
            }
            else
            {
                int num2 = st.top();
                st.pop();
                int num1 = st.top();
                st.pop();
                if (tokens[i] == "+")
                {
                    int num = num1 + num2;
                    st.push(num);
                }
                else if (tokens[i] == "-")
                {
                    int num = num1 - num2;
                    st.push(num);
                }
                else if(tokens[i] == "*")
                {
                    int num = num1 * num2;
                    st.push(num);
                }
                else
                {
                    int num = num1 / num2;
                    st.push(num);
                }
            }
        }
        int res = st.top();
        return res;
    }
};

2.6滑动窗口最大值(*)

题目
在这里插入图片描述

class Solution {
public:
    vector<int> maxSlidingWindow(vector<int>& nums, int k) 
    {
        if(nums.size() == 0 || k == 0) return {};
        deque<int> deque;
        vector<int> res(nums.size() - k + 1);
        for(int j = 0, i = 1 - k; j < nums.size(); i++, j++) {
            // 删除 deque 中对应的 nums[i-1]
            if(i > 0 && deque.front() == nums[i - 1])
                deque.pop_front();
            // 保持 deque 递减
            while(!deque.empty() && deque.back() < nums[j])
                deque.pop_back();
            deque.push_back(nums[j]);
            // 记录窗口最大值
            if(i >= 0)
                res[i] = deque.front();
        }
        return res;
    }
};

注意i从1-k开始!!!,即从第一个元素开始加入队列

2.7前k个高频元素(*)

题目
哈希表+优先队列
在这里插入图片描述

#include <iostream>
#include <vector>
#include <unordered_map>
#include <queue>
using namespace std;
class Solution {
public:
    vector<int> topKFrequent(vector<int>& nums, int k) 
    {
        unordered_map<int, int> um;
        for(auto& i : nums)
        {
            ++um[i];
        }
        priority_queue<pair<int, int>> pq;
        for(auto& i : um)
        {
            pq.push({i.second, i.first});
        }
        vector<int> res;
        while(k--)
        {
            res.push_back(pq.top().second);
            pq.pop();
        }
        return res;
    }
};
  • 5
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值