本章对代码随想录的栈和队列进行学习
什么是栈
栈是一种特殊的线性表,仅能在线性表的一端操作,栈顶允许操作,栈底不允许操作。
栈的特点是:单向操作,先进后出,或者说是后进先出,从栈顶放入元素的操作叫入栈,取出元素叫出栈。
什么是队列
队列与栈一样,也是一种线性表,不同的是,队列可以在一端添加元素,在另一端取出元素,也就是:先进先出。从一端放入元素的操作称为入队,取出元素为出队。
以C++为例,栈和队列是STL(C++标准库)里面的两个数据结构。
我们常用的SGI STL,若无指定底层实现,默认是以deque为缺省情况下栈的底层结构。
栈提供push 和 pop 等等接口,所有元素必须符合先进后出规则,所以栈不提供走访功能,也不提供迭代器(iterator)。
也可以指定vector为栈的底层实现,初始化语句如下:
std::stack<int, std::vector<int> > third//使用vector为底层容器的栈
队列中先进先出的数据结构,同样不允许有遍历行为,不提供迭代器, SGI STL中队列一样是以deque为缺省情况下的底部结构。
所以STL 队列也不被归类为容器,而被归类为container adapter( 容器适配器)
可以指定list 为起底层实现,初始化queue的语句如下:
std::queue<int, std::list<int>> third; // 定义以list为底层容器的队列
class MyQueue {
public:
stack<int> stIn;
stack<int> stOut;
MyQueue() {
}
void push(int x) {
stIn.push(x);
}
int pop() {
if(stOut.empty()){
while(!stIn.empty()){
stOut.push(stIn.top());
stIn.pop();
}
}
int result=stOut.top();
stOut.pop();
return result;
}
int peek() {
int res=this->pop();//复用了pop
stOut.push(res);
return res;
}
bool empty() {
return stIn.empty()&&stOut.empty();
}
};
/**
* Your MyQueue object will be instantiated and called as such:
* MyQueue* obj = new MyQueue();
* obj->push(x);
* int param_2 = obj->pop();
* int param_3 = obj->peek();
* bool param_4 = obj->empty();
*/
int peek() {
int res=this->pop();//注意,这里的this指针复用了pop
stOut.push(res);
return res;
}
力扣用队列实现栈
队列queue有front,栈stack有top
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;
while(!que2.empty()){
que2.pop();
}
return result;
}
int top() {
return que1.back();
}
bool empty() {
return que1.empty();
}
};
/**
* Your MyStack object will be instantiated and called as such:
* MyStack* obj = new MyStack();
* obj->push(x);
* int param_2 = obj->pop();
* int param_3 = obj->top();
* bool param_4 = obj->empty();
*/
class Solution {
public:
bool isValid(string s) {
/*if(s.size()%2!=0){
return false;
}*/
stack<char> st;
for(int i=0;i<s.size();i++){
if(s[i]=='(') st.push(')');
else if(s[i]=='{') st.push('}');
else if(s[i]=='[') st.push(']');
else if(st.empty()||st.top()!=s[i]) return false;//第三种情况右括号多,第二种情况中间不匹配
else st.pop();//匹配成功的括号则弹出
}
return st.empty();//第一种左括号多
}
};
class Solution {
public:
string removeDuplicates(string S) {
stack<char> st;
for(char s:S){
if(st.empty()||s!=st.top()){
st.push(s);
}else{
st.pop();//相等则弹出
}
}
string result="";
while(!st.empty()){
result+=st.top();
st.pop();//逆转字符
}
reverse(result.begin(),result.end());
return result;
}
};
也可以直接用result作栈
class Solution {//也可以直接用result作栈
public:
string removeDuplicates(string S) {
string result;//直接用字符串作栈
for(char s:S){
if(result.empty()||result.back()!=s){
result.push_back(s);
}
else{
result.pop_back();
}
}
return result;
}
}
class Solution {
public:
int evalRPN(vector<string>& tokens) {
stack<long long> st;
for(int i=0;i<tokens.size();i++){
if(tokens[i]=="+"||tokens[i]=="-"||tokens[i]=="*"||tokens[i]=="/"){
long long num1=st.top();
st.pop();
long long num2=st.top();
st.pop();
if(tokens[i]=="+")st.push(num2+num1);
if(tokens[i]=="-")st.push(num2-num1);
if(tokens[i]=="*")st.push(num2*num1);
if(tokens[i]=="/")st.push(num2/num1);
}else{
st.push(stoll((tokens[i])));//该函数将转换后的整数返回为long int类型的值
}
}
int result=st.top();
st.pop();
return result;
}
};
class Solution {
private:
class MyQueue{
public:
deque<int> que;
void pop(int value){//如果要弹出值的就是队列出口,则弹出
if(!que.empty()&&value==que.front()){
que.pop_front();
}
}
void push(int value){//如果压入的值大于队列尾号的数,就将队列后端的数值弹出,直到push的数值小于等于队列入口元素的数值为止
while(!que.empty()&&value>que.back()){
que.pop_back();
}
que.push_back(value);
}
int front(){//查询当前队列里的最大值 直接返回队列前端也就是front就可以了
return que.front();
}
};
public:
vector<int> maxSlidingWindow(vector<int>& nums, int k) {
MyQueue que;
vector<int> result;
for(int i=0;i<k;i++){//先将前k的元素放进队列
que.push(nums[i]);
}
result.push_back(que.front());//result 记录前k的元素的最大值
for(int i=k;i<nums.size();i++){
que.pop(nums[i-k]);
que.push(nums[i]);
result.push_back(que.front());
}
return result;
}
};
class Solution {
public:
class mycomparision{
public:
//小顶堆
bool operator()(const pair<int,int>&lhs,const pair<int,int>&rhs){
return lhs.second>rhs.second;
}
};
// 要统计元素出现频率
vector<int> topKFrequent(vector<int>& nums, int k) {
unordered_map<int,int>map;
for(int i=0;i<nums.size();i++){
map[nums[i]]++;
}
// 定义一个小顶堆,大小为k
// 对元素排序
priority_queue<pair<int,int>,vector<pair<int,int>>,mycomparision> pri_que;
// 用固定大小为k的小顶堆,扫描所有频率的数值
for(unordered_map<int,int>::iterator it=map.begin();it!=map.end();it++){
pri_que.push(*it);
if(pri_que.size()>k){ // 如果堆的大小大于了K,则队列弹出,保证堆的大小一直为k
pri_que.pop();
}
}
// 找出前K个高频元素,因为小顶堆先弹出的是最小的,所以倒序来输出到数组
vector<int>result(k);
for(int i=k-1;i>=0;i--){
result[i]=pri_que.top().first;
pri_que.pop();
}
return result;
}
};