赞
踩
Class stack<>实现出一个 stack(也称为 LIFO,后进先出)。你可以使用 push() 将任意数量的元素放入 stack(如下图所示),也可以使用 pop() 将元素依其插入的相反次序从容器中移除(此即所谓“后进先出[LIFO]”)。
stack 包含在头文件< stack >中:
#include <stack>
在头文件< stack >中,class stack 定义如下:
namespace std{
template <typename T,
typename Container = deque<T> >
class stack;
}
定义一个 int 类型的 stack:
stack<int> st;
Stack 的实现中只是很单纯地把各项操作转化为内部容器的对应调用(如下图所示)。你可以使用任何 sequence 容器支持 stack,只要它们提供以下成员函数: back()、push_back() 和 pop_back()。例如你可以使用 vector 或 list 来容纳元素;
stack<int, vector<int> > st;
Stack 的核心接口由三个成员函数提供:push()、 top() 和 pop()。
注意, pop() 移除下一个元素,但是并不返回它;top() 返回下一个元素,但是并不移除它。所以,如果你想移除 stack 的下一个元素同时返回它,那么这两个的接口可能有点麻烦,但如果你只是想移除下一个元素而并不想处理它,这样的安排就比较好。注意,如果 stack 内没有元素,调用 top() 和 pop() 会导致不明确的行为。你可以采用成员函数 size() 和 empty() 来检验容器是否为空。
如果你不喜欢 stack<> 的标准接口,轻易便可写出若干更方便的接口。
#include <iostream> #include <stack> using namespace std; int main(){ stack<int> st; st.push(1);st.push(2);st.push(3); printf("%d\n", st.top());//1--2--3 st.pop(); printf("%d\n", st.top());//1--2 st.pop(); st.top() = 66;//1-->66 st.push(4);//66--4 st.push(5);//66--4--5 st.pop();//66--4 while(!st.empty()){ printf("%d ", st.top()); st.pop(); } return 0; }
注意,当使用 nontrivial (译注:意指不凡的、复杂的)元素类型时,你可以考虑在安插“不再被使用的元素”时采用 move(),或是采用 emplace(),由 stack 内部创建元素(二者都始自C++11):
#include <iostream>
#include <stack>
using namespace std;
int main(){
stack<pair<string, string> > s;
auto p = make_pair("qw", "666");
s.push(move(p));
cout << s.top().first << " " << s.top().second << endl;
s.emplace("qwjy", "666");
cout << s.top().first << " " << s.top().second << endl;
return 0;
}
标准的 stack<> class 将运作速度置于方便性和安全性之上。但我通常并不很重视这些,所以我自己写了一个 stack class,拥有以下优势:
此外,我把一般人不常使用的成员函数如比较动作(comparison)略去。我的 stack class定义如下:
编写 hpp 文件,dev C++编写只需要保存是改成 .hpp 文件即可。
#ifndef STACK_HPP #define STACK_HPP #include <deque> #include <exception> template <typename T> class Stack{ protected: std:: deque<T> c; public: class ReadEmptyStack : public std::exception{ public: virtual const char* what() const throw(){ return "read empty stack"; } }; typename std::deque<T>::size_type size() const{ return c.size(); } bool empty() const{ return c.empty(); } void push(const T& elem){ c.push_back(elem); } T pop(){ if(c.empty()){ throw ReadEmptyStack(); } T elem(c.back()); c.pop_back(); return elem; } T& top(){ if(c.empty()){ throw ReadEmptyStack(); } return c.back(); } }; #endif
下面看一下使用的例子,代码如下:
#include <iostream> #include <exception> #include "Stack.hpp" using namespace std; int main(){ try{ Stack<int> st; st.push(1);//1 st.push(2);//1--2 st.push(3);//1--2--3 cout << st.pop() << endl;//1--2 cout << st.pop() << endl;//1 st.top() = 66;//1-->55 st.push(4);//66--4 st.push(5);//66--4--5 st.pop();//66--4 cout << st.pop() << endl;//66 cout << st.pop() << endl;//空 cout << st.pop() << endl;//报错 }catch(const exception& e){ cerr << "EXCEPTION: " << e.what() << endl; } return 0; }
Class queue<> 实现出一个 queue(也称为 FIFO [先进先出])。你可以使用 push() 将任意数量的元素放入 queue 中(如下图所示),也可以使用 pop() 将元素依其插入次序从容器中移除(此即所谓“先进先出 [FIFO]”)。换句话说,queue 是一个典型的数据缓冲构造。
queue 包含在头文件< queue > 中:
#include <queue>
在头文件< queue >中,class queue 定义如下:
namespace std{
template <typename T,
typename Container = deque<T> >
class queue;
}
例如下面的例子定义出了一个内含 string 的 queue:
queue<string> q;
实际上 queue 只是很单纯地把各项操作转化为内部容器的对应调用(如下图所示)。你可以使用任何 sequence 容器支持 queue,只要它们支持 front()、 back()、push_back() 和 pop_front() 等操作。
例如你可以使用 list 来容纳元素:
queue<string, list<string> > q;
Queue 的核心接口主要由成员函数push()、 front()、 back() 和 pop() 构成:
注意,pop() 虽然移除下一个元素,但是并不返回它,front() 和 back() 返回下一个元素,但并不移除它。所以,如果你想移除 queue 的下一一个元素,又想处理它,那就得同时调用 front() 和 pop()。这样的接口可能有点麻烦,但如果你只是想移除下一个元素而并不想处理它,这样的安排就比较好。注意,如果 queue 内没有元素,则 front()、back() 和 pop() 的执行会导致不确定的行为。你可以采用成员函数 size() 和 empty() 来检验容器是否为空。
#include <iostream> #include <queue> using namespace std; int main(){ queue<int> q; q.push(1);q.push(2);q.push(3); printf("%d\n", q.front());//1--2--3 q.pop(); printf("%d\n", q.front());//2--3 q.pop(); q.push(4);//3--4 q.push(5);//3--4--5 q.pop();//4--5 printf("%d\n", q.front());//4--5 q.pop(); printf("%d\n", q.front());//5 q.pop(); printf("size(): %d", q.size()); return 0; }
标准的 queue<> class 将运作速度置于方便性和安全性之上。但不是所有程序员都喜欢这样。你可以轻松提供你自己完成的一个 queue class,就像先前自己完成一个 stack class 一样(如上 stack class)。
#ifndef Queue_HPP #define Queue_HPP #include <deque> #include <exception> template <typename T> class Queue{ protected: std:: deque<T> c; public: class ReadEmptyQueue : public std::exception{ public: virtual const char* what() const throw(){ return "read empty queue"; } }; typename std::deque<T>::size_type size() const{ return c.size(); } bool empty() const{ return c.empty(); } void push(const T& elem){ c.push_back(elem); } T pop(){ if(c.empty()){ throw ReadEmptyQueue(); } T elem(c.front()); c.pop_front(); return elem; } T front(){ if(c.empty()){ throw ReadEmptyQueue(); } T elem(c.front()); return elem; } T back(){ if(c.empty()){ throw ReadEmptyQueue(); } T elem(c.back()); return elem; } }; #endif
下面看使用 Queue 的代码:
#include <iostream> #include <exception> #include "Queue.hpp" using namespace std; int main(){ try{ Queue<int> q; q.push(1);q.push(2);q.push(3); printf("%d\n", q.front());//1--2--3 q.pop(); printf("%d\n", q.front());//2--3 q.pop(); q.push(4);//3--4 q.push(5);//3--4--5 q.pop();//4--5 printf("%d\n", q.pop());//4--5 printf("%d\n", q.pop());//5 printf("size(): %d\n", q.size()); q.pop();//报错 // q.front();//报错 // q.back();//报错 }catch (const exception& e){ cerr << "EXCEPTION: " << e.what() << endl; } return 0; }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。