栈与队列

  1. 中缀表达式–>后缀表达式
    "a+bc+(de+f)g" --> abc+def+g+
    规则:使用符号栈存放运算符。
    (1)如果栈顶元素优先级高于或等于当前运算符,出栈。
    (2)’(‘最高优先级,但只能被’)'出栈。
string trans(string str)
{
	string res;
	stack<char> ops;
	map<char, int> pri = { {'+',1},{'-',1},{'*',2},{'/',2} };//优先级定义

	for (int i = 0; i < str.length(); i++)
	{
		if (str[i] == '+' || str[i] == '-' || str[i] == '*' || str[i] == '/')
		{//栈顶运算符优先级高于或等于当前运算符,出栈
			while (!ops.empty() && str[i] != '(' && pri[ops.top()] >= pri[str[i]])
			{
				res += ops.top();
				ops.pop();
			}//加入当前运算符
			ops.push(str[i]);
		}
		else if (str[i] == '(')
		{
			ops.push(str[i]);
		}
		else if (str[i] == ')')
		{//直到左括号为止。
			while (!ops.empty() && ops.top() != '(')
			{
				res += ops.top();
				ops.pop();
			}
			if (!ops.empty() && ops.top() == '(') ops.pop();
		}else
			res += str[i];
		
	}
	while (!ops.empty())
	{
		res += ops.top();
		ops.pop();
	}
	return res;
}
  1. 后缀表达式(逆波兰表达式)计算
class Solution {//遇到数字就入栈,遇到运算符就出战两个元素,一定是前面元素操作后面元素,再将结果入站,最后结果在栈里。
public:
	int evalRPN(vector<string> tokens) {
		stack<int> st;
		for (int i = 0; i < tokens.size(); i++)
		{
			if (tokens[i] == "+")
			{
				int a = st.top(); st.pop();
				int b = st.top(); st.pop();
				st.push(a + b);
			}
			else if (tokens[i] == "-")
			{
				int a = st.top(); st.pop();
				int b = st.top(); st.pop();
				st.push(b - a);
			}
			else if (tokens[i] == "*")
			{
				int a = st.top(); st.pop();
				int b = st.top(); st.pop();
				st.push(a * b);
			}
			else if (tokens[i] == "/")
			{
				int a = st.top(); st.pop();
				int b = st.top(); st.pop();
				st.push(int(b / a));
			}
			else st.push(atoi(tokens[i].c_str()));

		}
		return st.top();
	}
};
  1. 能查最小值的栈

题目描述
定义栈的数据结构,请在该类型中实现一个能够得到栈中所含最小元素的min函数(时间复杂度应为O(1))。

思路:
定义一个data栈和mins栈分别存放原始数据和最小值,注意两个栈长度相同。当push时如果值小于mins栈顶数字就入栈否则入mins的栈顶元素,这样就保证了mins栈顶元素一直是data栈中最小的。pop时一起出栈。
比如,data中依次入栈,5, 4, 3, 8, 10, 11, 12, 1
则min依次入栈,5, 4, 3,3,3, 3, 3, 1

class Solution {
public:
	void push(int value) {
		data.push(value);
		if (mins.empty())
			mins.push(value);
		else {
			if (mins.top() > value)
				mins.push(value);
			else
				mins.push(mins.top());
		}
	}
	void pop() {
		data.pop();
		mins.pop();
	}
	int top() {
		return data.top();
	}
	int min() {
		return mins.top();
	}
private:
	stack<int> data;
	stack<int> mins;
};

  1. 验证栈的弹出顺序

题目描述
输入两个整数序列,第一个序列表示栈的压入顺序,请判断第二个序列是否可能为该栈的弹出顺序。假设压入栈的所有数字均不相等。例如序列1,2,3,4,5是某栈的压入顺序,序列4,5,3,2,1是该压栈序列对应的一个弹出序列,但4,3,5,1,2就不可能是该压栈序列的弹出序列。(注意:这两个序列的长度是相等的)

思路:
只需要模拟出栈过程。在压栈过程中是有弹栈的,所以压栈的时候先押入部分元素,如果栈顶元素和出栈元素相同就持续弹栈,直到栈顶元素和出栈元素不同为止。当所有元素都入过栈后,直接出战所有元素,看是否与出战序列相同。

class Solution {
public:
    bool IsPopOrder(vector<int> pushV, vector<int> popV) {
        stack<int> st;
        int j = 0;
        for (int i = 0; i < pushV.size(); ++i)
        {
            while (!st.empty() && st.top() == popV[j])
            {
                st.pop();
                ++j;
            }
            st.push(pushV[i]);
        }
        while(!st.empty() && st.top()==popV[j])
        {
            st.pop();
            ++j;
        }
        if (!st.empty()) return false;
        return true;
}
};
  1. 队列实现栈
    整体思路:在队列中的数据维持“先入后出”顺序。
//两个队列实现栈
class MyStack {
private:
    queue<int> qu1, qu2;
public:
    MyStack() {

    }
    
    void push(int x) {
        qu2.push(x);
        while(!qu1.empty()){
            qu2.push(qu1.front());
            qu1.pop();
        }
        swap(qu1, qu2);
    }
    
    int pop() {
        int top = qu1.front();
        qu1.pop();
        return top;
    }
    
    int top() {
         return qu1.front();
    }
    
    bool empty() {
        return qu1.size() == 0;
    }
};
//其实一个队列就可:在push时将原来元素转移到新添加元素的后面
// "3-2-1 4" -> "4 3-2-1"
class MyStack {
private:
    queue<int> qu;
public:
    MyStack() {

    }
    
    void push(int x) {
        int size = qu.size();
        qu.push(x);
        while(size--){
            qu.push(qu.front());
            qu.pop();
        }
    }
    
    int pop() {
        int top = qu.front();
        qu.pop();
        return top;
    }
    
    int top() {
         return qu.front();
    }
    
    bool empty() {
        return qu.size() == 0;
    }
};
  • 队列实现栈
    整体思路:使用两个栈,在pop时不是把栈1所有元素转移到栈2,然后再转移回来,这样的时间复杂度是 O ( n ) O(n) O(n).
queue<int> qu;

void push(int x) {
	int sz = qu.size();
	qu.push(x);
	while (sz--) {
		qu.push(qu.front());
		qu.pop();
	}
}
void pop() {
	qu.pop();
}
int top() {
	return qu.front();
}

应该使用两个栈,栈1用来push栈2用来pop。pop时如果栈2空那就把栈1元素添加进来,由于两次入栈,元素顺序又保持“先入先出”,pop完后不用转移回栈1,后添加进来的元素肯定是比先进来的后出去。这样每个元素都是入栈两次,出栈两次,时间复杂度 O ( 1 ) O(1) O(1).

class MyQueue {
private: 
    stack<int> st1, st2;
public:
    /** Initialize your data structure here. */
    MyQueue() {

    }
    
    /** Push element x to the back of queue. */
    void push(int x) {
        st1.push(x);
    }
    
    /** Removes the element from in front of queue and returns that element. */
    int pop() {
        if(st2.empty()){
            while(!st1.empty()){
                st2.push(st1.top());
                st1.pop();
            }
        }
        int res = st2.top();
        st2.pop();
        return res;
    }
    
    /** Get the front element. */
    int peek() {
        if(st2.empty()){
            while(!st1.empty()){
                st2.push(st1.top());
                st1.pop();
            }
        }
        return st2.top();
    }
    
    /** Returns whether the queue is empty. */
    bool empty() {
        return st1.size() == 0 && st2.size() == 0;
    }
};
  1. 验证是否是有效的括号组合
    左括号入栈,右括号和栈顶比较。如果栈顶元素不匹配或战中没有元素就是无效组合。最后栈剩余元素也说明组合无效。
20. Share
Given a string containing just the characters '(', ')', '{', '}', '[' and ']', determine if the input string is valid.

An input string is valid if:

Open brackets must be closed by the same type of brackets.
Open brackets must be closed in the correct order.
Note that an empty string is also considered valid.
 class Solution {
 public:
	 bool isValid(string s) {
		 if (s.empty()) return true;
		 if (s.length() % 2) return false;

		 stack<char> st;
		 map<char, char> m = { {')','('},{']','['},{'}','{'} };
		 for (int i = 0; i < s.length(); i++)
		 {
			 if (s[i] == '(' || s[i] == '[' || s[i] == '{') st.push(s[i]);
			 else
			 {
				 if (st.empty() == false)
				 {
					 char top = st.top();
					 if (top == m[s[i]]) st.pop();
					 else return false;
				 }
				 else return false;
			 }
		 }
		 if(st.empty()) return true;
         else return false;
	 }
 };
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值