数据结构C++ --- Stack

一. 栈stack

stack也是一种线性结构, 其特点是LIFO, 后进先出. 最后进入栈的元素先出栈

stack是一个操作受限的线性结构, 底层空间可以是连续的也可以是不连续的

只需向上层提供对stack的入栈, 出栈, 取栈顶, 判断栈为空, 栈的大小等操作

二. STL中的stack

STL中对栈的描述:

1.stack是一种容器适配器,专门用在具有后进先出操作的上下文环境中,其删除只能从容器的一端进行
元素的插入与提取操作; 容器适配器即是对特定类封装作为其底层的容器,并提供一组特定
的成员函数来访问其元素

2.stack的底层容器可以是任何容器类模板或者一些其他特定的容器类,这些容器类应该支持以下操作:
empty:判空操作
back:获取尾部元素操作
push_back:尾部插入元素操作
pop_back:尾部删除元素操作

3.标准容器vector、deque、list均符合这些需求,默认情况下,如果没有为stack指定特定的底层容器,
默认情况下使用deque

1. STL中对栈的定义是容器适配器, 什么是容器适配器

    适配器是一种设计模式, 该模式是将一个类的接口转换成客户希望的另外一个接口

    简单来说 vector, list, deque 都有自己的底层空间结构, 而容器适配器(stack, queue)只是将其他已有的

    容器类进行了封装, 并提供了自己的接口

 

2. vector, deque, list都可以作为底层容器

    对于stack来说, 需要提供的接口是主要是push(入栈)和pop(出栈)和top(取栈顶元素), 底层容器最好提供高效的接口

     vector不考虑增容时支持O(1)的push_back, pop_back和随机访问

     list支持O(1)的push_back, pop_back和back

     deque双端队列是一种复杂的数据结构,底层空间由多个不连续的存储块构成, 支持随机访问, 支持O(1)的头尾修改

 

3. C++选用deque作为STL stack, queue底层的容器

    1. stack和queue不需要遍历(因此stack和queue没有迭代器),只需要在固定的一端或者两端进行操作。
    2. 在stack中元素增长时,deque比vector的效率高;queue中的元素增长时,deque不仅效率高,而且内
    存使用率高

三. 实现一个Stack

自己实现一个类似STL中的栈, 底层容器使用上一次写的Vector

template<class T, class Container = Vector<T>>
class Stack{
public:
  Stack(){} // 构造, 自动调用Vector的构造

  T Top(){
    return _con.back(); // 返回Vector的最后一个元素
  }

  void Push(const T& x){ // Push_Back到Vector
    _con.push_back(x);
  }

  void Pop(){
    _con.pop_back();   // 删除Vector的尾部元素
  }

  bool Empty(){
    return _con.size() == 0; // Vector的size是否为0
  }

  int Size(){
    return _con.size();     // 返回Vector的size
  }
private:
  Container _con;
};

四. 有关栈的简单笔试题

1. LeetCode  20. 有效的括号 https://leetcode-cn.com/problems/valid-parentheses/

给定一个只包括 '(',')','{','}','[',']' 的字符串,判断字符串是否有效。

有效字符串需满足:

  1.左括号必须用相同类型的右括号闭合。
  2.左括号必须以正确的顺序闭合。
注意空字符串可被认为是有效字符串。

思路: 使用一个栈, 遍历字符串, 遇到左括号入栈, 遇到右括号和栈顶元素比较

bool isValid(string s) {
        if (s.size() % 2 != 0) return false;
        
        std::stack<int> _stack;
        for(auto ch : s){
            if (ch == '(' || ch == '[' || ch == '{'){
                _stack.push(ch);    // 左括号入栈
            }
            else{
                if (_stack.empty()) return false;
                
                char left = _stack.top();   // 右括号比较栈顶元素
                _stack.pop();
                if (ch == ')' && left != '(')
                    return false;
                else if (ch == ']' && left != '[')
                    return false;
                else if (ch == '}' && left != '{')
                    return false;
            }
        }
        
        if (!_stack.empty())
            return false;
        else
            return true;
    }

2. LeetCode 155. 最小栈  https://leetcode-cn.com/problems/min-stack/submissions/

设计一个支持 push,pop,top 操作,并能在常数时间内检索到最小元素的栈。

push(x) -- 将元素 x 推入栈中。
pop() -- 删除栈顶的元素。
top() -- 获取栈顶元素。
getMin() -- 检索栈中的最小元素。

思路: 使用两个栈, 一个存数据, 一个存当前数据栈中的最小值(一定要<=), 存最小值相当于存当前数据入栈时的最小值

class MinStack {
public:
    MinStack() {
        
    }
    
    void push(int x) {
        _eleStack.push(x); // 数据直接加入数据栈
        if (_minStack.empty() || x <= _minStack.top()) // = 很重要, 不然pop会有问题
            _minStack.push(x);
    }
    
    void pop() {
        if (_minStack.top() == _eleStack.top()){ // 如果删除的数据是最小的要从最小栈删除
            _minStack.pop();
        }
        _eleStack.pop();
 
                                                
    }
    
    int top() {
        return _eleStack.top(); 
    }
    
    int getMin() {
        return _minStack.top();
    }
private:
    std::stack<int> _eleStack; // 数据栈
    std::stack<int> _minStack; // 存最小值的栈
};

 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值