STL版本
- HP STL 其他版本的C++ STL,一般是以HP STL为蓝本实现出来的,HP STL是C++ STL的第一个实现版本,而且开放源代码。
- P.J.Plauger STL 由P.J.Plauger参照HP STL实现出来的,被Visual C++编译器所采用,不是开源的。
- SGI STL 由Silicon Graphics Computer Systems公司参照HP STL实现,被Linux的C++编译器GCC所采用,SGI STL是开源软件,源码可读性甚高。
栈与队列
- 队列是先进先出,栈是先进后出。
栈
- C++中stack(栈)是容器改编的。stack不提供迭代器来遍历stack空间,只有特定的方法 top push pop empty等等。
- 我们使用的stack是属于SGI STL。SGI STL栈如果没有指定底层实现的话,默认是用双端队列deque实现的。当然,栈的底层实现可以是vector,deque,list 都是可以的, 主要就是数组和链表的底层实现。
- 我们也可以指定vector为栈的底层实现,初始化语句如下:
std::stack<int, std::vector<int> > third; // 使用vector为底层容器的栈
- 堆栈的语法:为了创建堆栈,我们必须在代码中包含
<stack>头文件。
与堆栈相关的功能有:
队列
- 队列中先进先出的数据结构,同样不允许有遍历行为,不提供迭代器, SGI STL中队列一样是以deque为缺省情况下的底部结构。
- 也可以指定list 为起底层实现,初始化queue的语句如下:
std::queue<int, std::list<int>> third; // 定义以list为底层容器的队列
-
STL 队列也不被归类为容器,而被归类为container adapter( 容器适配器)。
-
单向队列queue相关函数: |Method| Definition | | :----: | :----: | | queue::empty() | 返回队列是否为空。| | queue::size() | 返回队列的大小。 | | queue::swap() | 交换两个队列的内容,但队列必须是同一类型,尽管大小可能不同| | queue::emplace() | 在队列容器中插入一个新元素,新元素被添加到队列的末端。| | queue::front() | 返回对队列中第一个元素的引用。| | queue::back() | 返回对队列中最后一个元素的引用。 | | queue::push(g) | 将元素'g'添加到队列的末端。| | queue::pop() | 删除队列的第一个元素。|
-
push_front()队列头插入push_back()队列尾部插入pop_front()队列头删除pop_back()队列尾部删除
题目
232. 用栈实现队列
思路和题解
设定两个栈,一个栈stin用于存进的元素,之后再把这个栈的所有元素存入另一个栈stout,之后对stout里面元素的操作则和对队列的元素操作顺序一致了。详细见下图:
- 注意点:本题要注意的是什么时候从stin里面把元素放入stout里面。判断条件一定是stout里面为空了,才把stin的元素全部导入stout里面,否则元素顺序就把打乱了。
- 在push数据的时候,只要数据放进输入栈stin就好,但在pop的时候,操作就复杂一些,输出栈如果为空,就把进栈数据全部导入进来(注意是全部导入) ,再从出栈弹出数据,如果输出栈不为空,则直接从出栈弹出数据就可以了。
class MyQueue {
public:
//定义两个栈
stack<int> stin;
stack<int> stout;
MyQueue() {
}
void push(int x) {
stin.push(x);//栈加元素的函数
}
int pop() {
//判断stout是否为空,是空的就把stin里的全部放入stout
if(stout.empty()){
while(stin.empty()!=true){
//加完一个删一个
stout.push(stin.top());
stin.pop();
}
}
//得到stout的第一个元素
int result = stout.top();
//再把stout的第一个元素删除
stout.pop();
return result;
}
int peek() {
int res = this->pop(); // 直接使用上面pop函数,但是这个pop函数会删除stout的第一个元素
stout.push(res); // 所以再添加回去,因为peek函数是不删除元素的
return res;
}
bool empty() {
if(stout.empty() && stin.empty()) return true;
return false;
}
};
225. 用队列实现栈
使用一个队列实现
class MyStack {
public:
//定义一个双端队列
deque<int> d;
MyStack() {
}
void push(int x) {
d.push_back(x);//从后加入队列
}
int pop() {
int result = d.back(); //返回队列最后一个元素
d.pop_back();//删除队列最后一个元素
return result;
}
int top() {
int result = this->pop();//调用上面的pop函数,因为top功能不删除元素
d.push_back(result);//所以再把元素加回去
return result;
}
bool empty() {
if(d.empty()){return true;}
return false;
}
};
使用两个队列实现(复杂)
用两个队列que1和que2实现队列的功能,que2其实完全就是一个备份的作用,把que1最后面的元素以外的元素都备份到que2,然后弹出que1最后面的元素(即模拟了栈的后进先出),再把其他元素从que2导回que1。
class MyStack {
public:
queue<int> que1;
queue<int> que2; // 辅助队列,用来备份
/** Initialize your data structure here. */
MyStack() {
}
/** Push element x onto stack. */
void push(int x) {
que1.push(x);
}
/** Removes the element on top of the stack and returns that element. */
int pop() {
int size = que1.size();
size--;//留下最后一个元素
while (size--) { // 将que1 导入que2,但要留下最后一个元素
que2.push(que1.front());
que1.pop();
}
int result = que1.front(); // 留下的最后一个元素就是要返回的值
que1.pop();
que1 = que2; // 再将que2赋值给que1
// 清空que2
while (!que2.empty()) {
que2.pop();
}
return result;
}
/** Get the top element. */
int top() {
return que1.back();
}
/** Returns whether the stack is empty. */
bool empty() {
return que1.empty();
}
};