标准模板库STL(续)
六、堆栈
stack 底层容器vector/deque/list
push push_back
pop pop_back
top back
size size
empty empty
... ...
#include <stack>
stack<int, vector<int> > si;
stack<string, list<string> > ss;
stack<double> sd; // 缺省底层容器deque
template<typename T, typename C>
stack {
public:
void push (const T& data) {
m_container.push_back (data);
}
void pop (void) {
m_conainer.pop_back ();
}
T& top (void) {
return m_container.back ();
}
private:
C m_container;
};
/*
* 适配器练习- stack
*
* */
#include <iostream>
#include <stack>
#include <vector>
using namespace std;
int main (void) {
stack<string, vector<string> > ss;
ss.push ("吃饭");
ss.push ("喜欢");
ss.push ("偶");
while (! ss.empty ()) {
cout << ss.top ();
ss.pop ();
}
cout << endl;
return 0;
}
七、队列
queue 底层容器deque/list (p.s.不可以是vector,因为vector没有提供pop_front)
push push_back
pop pop_front
front front
back back
size size
empty empty
...
queue<int, list<int> > qi;
queue<string> qs; // 缺省底层容器deque
/*
* 适配器练习- queue
* */
#include <iostream>
#include <queue>
#include <list>
using namespace std;
int main (void) {
queue<string, list<string> > qs;
qs.push ("我");
qs.push ("要");
qs.push ("吃");
qs.push ("饭");
while (! qs.empty ()) {
cout << qs.front ();
qs.pop ();
}
cout << endl;
return 0;
}
八、优先队列(priority_queue)
优者先出
底层容器:vector/deque/list,缺省deque
通过类型实参以比较器的形式定义比较规则
/*
* 适配器练习- priority queue
*
* */
#include <iostream>
#include <queue>
using namespace std;
class Student {
public:
Student (const string& name, float score) :
m_name (name), m_score (score) {}
void print (void) const {
cout << m_name << "," << m_score << endl;
}
bool operator< (const Student& student) const {
return m_score > student.m_score;
}
private:
string m_name;
float m_score;
};
class CmpInt {
public:
bool operator() (int a, int b) {
return a > b;
}
};
int main (void) {
// priority_queue<int> pqi;
priority_queue<int, deque<int>, CmpInt> pqi;
pqi.push (23);
pqi.push (12);
pqi.push (23);
pqi.push (27);
pqi.push (19);
while (! pqi.empty ()) {
cout << pqi.top () << ' ';
pqi.pop ();
}
cout << endl;
priority_queue<Student> pqs;
pqs.push (Student ("张飞", 65));
pqs.push (Student ("关羽", 60));
pqs.push (Student ("赵云", 85));
pqs.push (Student ("刘备", 95));
pqs.push (Student ("曹操", 25));
while (! pqs.empty ()) {
pqs.top ().print ();
pqs.pop ();
}
return 0;
}
九、映射(map)
1.key-value对(pair)的容器,通过pair表示key-value对。
post script:关于pair
template<typename FIRST, typename SECOND>
class pair {
prublic:
...
FIRST first;
SECOND second;
};
2.key唯一且升序。
3.支持下标运算符,可以用[key]访问value。
4.可以通过比较器类型自定义key升序的规则。
/*
* map练习
* */
#include <iostream>
#include <map>
using namespace std;
class Candidate {
public:
Candidate (const char* name = "") :
m_name (name), m_votes (0) {}
const string& name (void) const {
return m_name;
}
size_t votes (void) const {
return m_votes;
}
void vote (void) {
++m_votes;
}
private:
string m_name;
size_t m_votes;
};
int main (void) {
map<char, Candidate> mc;
mc.insert (make_pair ('B', "赵云"));
mc.insert (pair<char, Candidate> ('A', "张飞"));//构造一个pair的对象放入map对象里
mc['D'] = "刘备";
mc['E'] = "曹操";
mc['C'] = "关羽";
mc['D'] = "黄忠";//因为key唯一且升序,所以这里会造成'D'不再与"刘备"形成映射
mc.insert (pair<char, Candidate> ('A', "马超"));//使用map的成员函数insert时候,insert判断出key已经与其他value形成映射,那么会忽略此次的insert
typedef map<char, Candidate>::iterator IT;
typedef map<char, Candidate>::const_iterator CIT;
for (size_t i = 0; i < 10; ++i) {
for (CIT it=mc.begin (); it != mc.end (); ++it)
cout << '(' << it->first << ')'
<< it->second.name () << ' ';
cout << endl << "请投下宝贵的一票:" << flush;
char key;
cin >> key;
IT it = mc.find (key);
if (it == mc.end ()) {
cout << "此票作废!" << endl;
continue;
}
it->second.vote ();
}
CIT win = mc.begin ();
for (CIT it = mc.begin (); it != mc.end (); ++it){
cout << it->second.name () << "获得"
<< it->second.votes () << "票。" << endl;
if (it->second.votes () > win->second.votes ())
win = it;
}
cout << "恭喜" << win->second.name () << "同学当选"
"为首席保洁员!" << endl;
return 0;
}
/*
*练习:编写程序,统计一个文本文件中每个单词出现的频率。按照词汇表的顺序打印输出。
*apple : 2
*beijing : 2
*c++ : 3
*...
* */
#include <iostream>
#include <fstream>
#include <map>
#include <cstring>
using namespace std;
class CmpStr {
public:
bool operator() (const string& a,
const string& b) const {
return strcasecmp (a.c_str (),
b.c_str ()) < 0;
}
};
int main (int argc, char* argv[]) {
if (argc < 2) {
cerr << "用法:" << argv[0] << " <文件>"<<endl;
return -1;
}
ifstream ifs (argv[1]);
if (! ifs) {
perror ("打开文件失败");
return -1;
}
map<string, int, CmpStr> msi;
string word;
while (ifs >> word)
++msi[word];
ifs.close ();
for (map<string, int>::iterator it = msi.begin ();
it != msi.end (); ++it)
cout << it->first << " : " << it->second<<endl;
return 0;
}
十、集合
/*
*set练习
*/
#include <iostream>
#include <set>
#include <fstream>
using namespace std;
int main (void) {
ifstream ifs ("test.txt");
set<string> ss;
string word;
while (ifs >> word)
ss.insert (word);
ifs.close ();
for (set<string>::iterator it = ss.begin ();
it != ss.end (); ++it)
cout << *it << endl;
cout << "共" << ss.size () << "个不同单词。"
<< endl;
return 0;
}
十一、多重映射
key可重复,升序,迭代时key相同的元素相邻。
/*
*multimap练习
*/
#include <iostream>
#include <map>
using namespace std;
int main (void) {
multimap<string, int> msi;
msi.insert (make_pair ("张飞", 100000));
msi.insert (make_pair ("赵云", 200000));
msi.insert (make_pair ("张飞", 300000));
msi.insert (make_pair ("关羽", 400000));
msi.insert (make_pair ("赵云", 500000));
msi.insert (make_pair ("关羽", 600000));
typedef multimap<string, int>::const_iterator CIT;
for (CIT it = msi.begin (); it != msi.end ();++it)
cout << it->first << " : " << it->second<<endl;
cout << "-------------" << endl;
for (CIT it = msi.begin (); it != msi.end();/*++it*/){
string key = it->first;
CIT end = msi.upper_bound (key);//upper_bound(key)成员函数返回和参数key相匹配的所有记录中最后一条记录的下一条记录的迭代器
int sum = 0;
for (; it != end; ++it)
sum += it->second;
cout << key << " : " << sum << endl;
// --it;
}
return 0;
}
十二、多重集合
/*
*multiset练习
*/
#include <iostream>
#include <set>
using namespace std;
int main (void) {
const char* candidates[] = {
"张飞", "赵云", "关羽", "刘备", "曹操", NULL};
multiset<string> ms;
for (size_t i = 0; i < 10; ++i) {
for (size_t i = 0; candidates[i]; ++i)
cout << '(' << char ('A' + i) << ')'
<< candidates[i] << ' ';
cout << endl << "请投下您庄严的一票:" <<flush;
char key;
cin >> key;
if (key < 'A' || 'E' < key) {
cout << "此票作废!" << endl;
continue;
}
ms.insert (candidates[key-'A']);
}
multiset<string>::iterator win = ms.begin ();
for (multiset<string>::iterator it = ms.begin ();
it != ms.end (); ++it) {
cout << *it << "获得" << ms.count (*it)
<< "票。" << endl;
if (ms.count (*it) > ms.count (*win))
win = it;
it = ms.upper_bound (*it);
--it;
}
cout << "热烈祝贺" << *win << "当选垃圾长!"
<< endl;
return 0;
}
十三、泛型算法
1.STL中包含60种泛型算法,其中包含23种非修改算法,如find,37种修改算法,如sort。
2.STL中的泛型算法多数都会迭代器实现对容器元素的访问。
3.STL中的泛型算法凡是涉及到比较大小的算法,都支持两种比较方案——“<”运算符和比较器函数对象。
4.除了STL中的容器以外,程序员也可以使自定义的容器,获得STL泛型算法的支持,只要改自定义类型能够支持此算法对迭代器的使用规则即可。
/*
*练习:假设现在有任意两个容器,请实现一个泛型的容器拷贝函数,用将一个容器中数据拷贝到另一个容器中。
*/
#include <vector>
#include <deque>
#include <list>
template<typename iterator>
void print(iterator begin, iterator end)
{
while (begin != end) {
cout << *begin++ << ' ' << flush;
}
cout << endl;
return 0;
}
template<typename IT1, typename IT2>
void my_copy (IT1 begin, IT1 end, IT2 to) {
while (begin != end)
//*(to++) = *(begin++);
*to++ = *begin++;
}
int main (void) {
int arr1[5] = {10, 20, 30, 40, 50};
int arr2[5];
copy (arr1, arr1 + 5, arr2);
print (arr2, arr2 + 5);
vector<int> vec (5);
copy (arr1, arr1 + 5, vec.begin ());
print (vec.begin (), vec.end ());
deque<int> deq (5);
copy (vec.begin (), vec.end (), deq.begin ());
print (deq.begin (), deq.end ());
list<int> lst (5);
copy (deq.begin (), deq.end (), lst.begin ());
print (lst.begin (), lst.end ());
return 0;
}