标签:顺序 调用 tmp class width war instant 有一个 pac
专题5-数据结构
C++ Primer P329好好研读,stack,queue,priority_queue都是顺序容器适配器adaptor。(接受一种已有的容器类型,使其行为看起来像另一种事物一样)
stack | 默认基于deque实现,除array和forward_list以外的容器都可以 |
queue | 默认基于deque实现,可以构造于list和deque之上,但是不能基于vector进行构造 |
priority_queue | 默认基于vector实现,最大堆max-heap,可以基于vetor和deque,但是不能基于list(需要随机访问能力) |
1、基础知识
1.1、stack栈
s.pop() | 删除栈顶元素 | O(1) |
s.push() | 压入元素 | O(1) |
s.top() | 返回首元素,但是不删除 | O(1) |
C++ primer P330
queue模板类的定义在<queue>头文件中。记住队列没有top()函数。
与stack模板类很相似,queue模板类也需要两个模板参数,一个是元素类型,一个容器类型,元素类型是必要的,容器类型是可选的,默认为deque类型。
定义queue对象的示例代码如下:
queue<int> q1; queue<double> q2;
queue的基本操作有:
q.push(x) | 入队,将x接到队列的末端 | 时间复杂度是O(1) |
q.pop() | 出队,弹出队列的第一个元素,注意,并不会返回被弹出元素的值 | 时间复杂度是O(1) |
q.front() | 访问队首元素,即最早被压入队列的元素 | 时间复杂度是O(1) |
q.back() | 访问队尾元素,即最后被压入队列的元素 | 时间复杂度是O(1) |
q.empty() | 判断队列空 | |
q.size() | 访问队列中的元素个数 |
队列经常用于BFS,之前总结过BFS要利用queue + unordered_map实现,还有就是二叉树的层次遍历。
1.3、priority_queue
主要操作是:pop(),top(),push()。
priority_queue利用一个最大堆完成,最大堆是一个以vector表现的完全二叉树,所以缺省情况下它的底部容器是vector。,queue以底部容器完成其所有的工作,具有这种“修改某物接口,形成另一种风貌”之性质者,称为adapter(适配器)。
priority_queue 对于基本类型的使用方法相对简单。他的模板声明带有三个参数,priority_queue<Type, Container, Functional>,Type 为数据类型, Container 为保存数据的容器,Functional 为元素比较方式。
Container 必须是用数组实现的容器,比如 vector, deque 但不能用 list。STL里面默认用的是 vector. 比较方式默认用 operator< , 所以如果你把后面俩个参数缺省的话,优先队列就是大顶堆,队头元素最大。
如果要用到小顶堆,则一般要把模板的三个参数都带进去。STL里面定义了一个仿函数 greater<>,对于基本类型可以用这个仿函数声明小顶堆。
#include <iostream> #include <queue> using namespace std; int main(){ priority_queue<int, vector<int>, greater<int> > q; for( int i= 0; i< 10; ++i ) q.push( rand() ); while( !q.empty() ){ cout << q.top() << endl; q.pop(); } getchar(); return 0; }
**对于自定义类型,则必须自己重载 operator< 或者自己写仿函数**
1)重载 operator<(自己联想一下每次弹出最小元素的queue形式,{3,2,1}所以必须是返回a.x> b.x;)sort默认是小于排序,从大到小排序,所以重载的时候需要operator<。
bool operator>( Node left, Node right ){ if( left.x== right.x )
return left.y> right.y; return left.x> right.x; }
#include <iostream> #include <queue> using namespace std; struct Node{ int x, y; Node( int a= 0, int b= 0 ): x(a), y(b) {} }; bool operator<( Node a, Node b ){ if( a.x== b.x ) return a.y> b.y; return a.x> b.x; } int main(){ priority_queue<Node> q; for( int i= 0; i< 10; ++i ) q.push( Node( rand(), rand() ) ); while( !q.empty() ){ cout << q.top().x << ‘ ‘ << q.top().y << endl; q.pop(); } getchar(); return 0; }
2)自己写仿函数
自定义类型重载 operator< 后,声明对象时就可以只带一个模板参数。但此时不能像基本类型这样声明priority_queue<Node, vector<Node>, greater<Node> >;原因是 greater<Node> 没有定义,如果想用这种方法定义
则可以按如下方式:
记住调用的时候格式为:priority_queue<Node, vector<Node>, cmp> q;
struct cmp{ bool operator() ( Node a, Node b ){ if( a.x== b.x ) { return a.y> b.y; } return a.x> b.x; } };
#include <iostream> #include <queue> using namespace std; struct Node{ int x, y; Node( int a= 0, int b= 0 ): x(a), y(b) {} }; struct cmp{ bool operator() ( Node a, Node b ){ if( a.x== b.x ) return a.y> b.y; return a.x> b.x; } }; int main(){ priority_queue<Node, vector<Node>, cmp> q; for( int i= 0; i< 10; ++i ) q.push( Node( rand(), rand() ) ); while( !q.empty() ){ cout << q.top().x << ‘ ‘ << q.top().y << endl; q.pop(); } getchar(); return 0; }
2、leetcode题目实战
2.1 155. Min Stack
https://leetcode.com/problems/min-stack/#/description
思路:使用两个栈,一个栈存正常数据,另一个栈记录每个元素对应的最小值是多少,这题细节,压入MinStack的时候,一定要使用if_else,minStack为空的时候要单独考虑,top()操作是返回stack中的数据。
class MinStack { public: /** initialize your data structure here. */ stack<int> s; stack<int> minStack; MinStack() { } void push(int x) { s.push(x); if(minStack.empty()){ minStack.push(x); } else{//总是忘记加上else,只有非空的时候才能这样 minStack.push(min(x,minStack.top())); } } void pop() { if(!s.empty()){ s.pop(); } if(!minStack.empty()){ minStack.pop(); } return; } int top() {//这里的top返回的是当前元素,不是需要返回最小值 if(!s.empty()){ return s.top(); } return 0; } int getMin() { if(!minStack.empty()){ return minStack.top(); } return 0; } }; /** * Your MinStack object will be instantiated and called as such: * MinStack obj = new MinStack(); * obj.push(x); * obj.pop(); * int param_3 = obj.top(); * int param_4 = obj.getMin(); */
2.2 232. Implement Queue using Stacks
https://leetcode.com/problems/implement-queue-using-stacks/#/description
思路:这题自己思路不清晰,要理顺。使用两个栈oldStack和newStack,其中newStack总是存储目前压入的元素,在pop和front操作前,如果oldStack中有元素,就直接弹出oldStack的元素,只有oldStack为空的时候,才将newStack中的元素弹出压入到oldStack中。
class MyQueue { public: /** Initialize your data structure here. */ stack<int> newStack,oldStack;//newStack总是存储最新压入的元素 MyQueue() { } /** Push element x to the back of queue. */ void push(int x) { newStack.push(x); } /** Removes the element from in front of queue and returns that element. */ int pop() { if(oldStack.empty()){ while(!newStack.empty()){ oldStack.push(newStack.top()); newStack.pop(); } } int tmp = oldStack.top(); oldStack.pop(); return tmp; } /** Get the front element. */ int peek() { if(oldStack.empty()){ while(!newStack.empty()){ oldStack.push(newStack.top()); newStack.pop(); } } return oldStack.top(); } /** Returns whether the queue is empty. */ bool empty() { return newStack.empty() && oldStack.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(); */
2.3 225. Implement Stack using Queues
https://leetcode.com/problems/implement-stack-using-queues/#/description
思路:这题有一个非常简单巧妙无敌的方法,除了push操作其他操作都和queue正常操作一样,使用一个队列就可以实现,将新元素压入queue,然后弹出一个front,再压入到queue中,这样就可以按照stack的顺序保存元素了。
4是需要压入的元素,{1,2,3}是已经压入的元素,然后将123弹出压入重新压入queue,就形成了{1‘,2‘,3’,4};
class MyStack { public: /** Initialize your data structure here. */ queue<int> q; MyStack() { } /** Push element x onto stack. */ void push(int x) { q.push(x); for(int i = 0;i < q.size() - 1;++i){ q.push(q.front()); q.pop(); } } /** Removes the element on top of the stack and returns that element. */ int pop() { int tmp = q.front(); q.pop(); return tmp; } /** Get the top element. */ int top() { return q.front(); } /** Returns whether the stack is empty. */ bool empty() { return q.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(); */
标签:顺序 调用 tmp class width war instant 有一个 pac
原文地址:http://www.cnblogs.com/dingxiaoqiang/p/7157445.html