一、标准模板库(STL)
(p.s. STL中的常用实用工具
auto_ptr
string
pair
)
1.定义了一系列的容器模板(类模板),实现泛型化的数据结构。
1)向量(vector, 这里说的"向量"就是数组), 向量内存连续,支持下标访问和随机迭代,只有在尾部进行插入和删除效率才比较高。
2)列表(list),内存不连续,不支持下标访问和随机迭代,在任何位置进行插入和删除效率都很高。
3)双端队列(deque),内存连续,支持下标访问和随机迭代,在首尾两端进行插入和删除效率都比较高。
以上三种合称为线性容器。
4)堆栈(stack),后进先出
5)队列(queue),先进先出
6)优先队列(priority_queue),优者先出
以上三种合称为适配器容器,通过某种线性容器适配。
7)映射(map),是键值对(KVP)的集合,按键升序,键唯一。 采用了有序二叉树(二叉搜索树)数据结构实现。
8)集合(set),没有值只有键的映射, 按键升序。
9)多重映射(multimap),允许重复键的映射,即键不唯一。按键升序。
10)多重集合(multiset),没有值只有键的多重映射。按键升序。
以上四种合称为关联容器。通过有序树表达数据的关联性。按键升序。
2.泛型函数(函数模板)
template<typename T>
void swap (T& a, T& b) {
T c = a;
a = b;
b = c;
}
template<typename IT>
void print (IT begin, IT end) {
while (begin != end)
cout << *begin++ << ' ';
cout << endl;
}
int a[5] = {1, 2, 3, 4, 5};
print (a, a + 5);
List list;
list.push_back (...);
...
print (list.begin (), list.end ());
1 /*
2 * STL函数for_each练习
3 *
4 * */
5 #include <iostream>
6 #include <algorithm>
7 using namespace std;
8 /*
9 template<typename IT, typename DOIT>
10 void for_each (IT begin, IT end, DOIT doit) {
11 while (begin != end)
12 doit (*begin++);
13 }
14 */
15 void print (int& x) {
16 cout << x << endl;
17 }
18 void add (int& x) {
19 ++x;
20 }
21 int main (void) {
22 int a[5] = {1, 2, 3, 4, 5};
23 for_each (a, a + 5, print);
24 for_each (a, a + 5, add);
25 for_each (a, a + 5, print);
26 return 0;
27 }
二、STL容器共性
1.所有的容器都支持拷贝构造和拷贝赋值,可以完整意义上的容器对象副本。
2.所有的容器都支持“==”运算符。
(p.s.容器的相等:容器的类型相同,容器中元素的类型相同,容器中元素的个数相等,对应元素还要满足相等性的判断)
3.容器中元素都是放入了源对象拷贝,而非源对象本身。
int b;
int a[3];
a[0] = b;
a[0]++;
4.容器中元素需要支持完整的拷贝语义。
(p.s. auto_ptr不适合放在容器中使用, 因为auto_ptr中为了防止double free把拷贝构造作成了是一种传递拷贝,不是真正意义上的拷贝)
5.如果需要对容器的元素进行排序或者查找操作,该元素的类型还需要支持“<”和“==”操作符。
三、向量(vector)
1.基本特点
1)连续内存和下标访问
2)动态内存管理
int a[10];
int *b = new int[10];
3)通过预分配内存空间减小动态内存管理的额外开销
4)可以再随机位置做插入和删除,但只有在接近尾部的操作才是高效的。
2.定义变量
#include <vector>
using namespace std;
vector<int> vi;
vector<string> vs;
3.迭代器
vector<...>::iterator - 正向迭代器
vector<...>::const_iterator - 常正向迭代器
vector<...>::reverse_iterator - 反向迭代器
vector<...>::const_reverse_iterator - 常反向迭代器
向量的四种迭代器都是随机迭代器,可以和整数做加减运算。
通过vector<...>调用,begin()返回起始迭代器,end()返回终止迭代器,最后一个元素的下一个位置。rbegin()返回起始反向迭代器,rend()返回终止反向迭代器。
通过const vector<...>&/*调用以上函数,返回的将是const_iterator/const_reverse_interator。
注意:任何容器,在结构性修改之前获得的迭代器,有可能因为这种修改而失效,或者不能标识正确的位置,这时候如果要继续使用迭代器,最好重新初始化迭代器。
4.预分配和初始化
vector<int> vi (10);
将vi初始化10个int元素,初始值为0。
vector<类> vc (10);
将vi初始化10个类类型的元素,通过无参构造函数初始化。
vector<int> vi (10, 8);
将vi初始化10个int元素,初始值为8。
vector<类> vc (10, 类 (...));
将vi初始化10个类类型的元素,通过拷贝构造函数初始化。
1 /*
2 *vector举例
3 */
4 #include <iostream>
5 #include <vector>
6 using namespace std;
7 class A {
8 public:
9 A (int i = 0) : m_i (i) {};
10 int m_i;
11 };
12 void print (const vector<int>& vi) {
13 size_t size = vi.size ();
14 cout << size << endl;
15 for (size_t i = 0; i < size; ++i)
16 cout << vi[i] << ' ';
17 cout << endl;
18 }
19 int main (void) {
20 vector<int> vi;
21 vi.push_back (10);
22 vi.push_back (20);
23 vi.push_back (30);
24 vi.push_back (20);
25 vi.push_back (10);
26 print (vi);
27 vi.pop_back ();
28 print (vi);
29 ++vi.front ();
30 vi.back () = 100;
31 cout << vi.front () << ' ' << vi.back () << endl;
32 typedef vector<int>::iterator IT;
33 typedef vector<int>::const_iterator CIT;
34 typedef vector<int>::reverse_iterator RIT;
35 typedef vector<int>::const_reverse_iterator CRIT;
36 for (IT it = vi.begin (); it != vi.end (); ++it)
37 ++*it;
38 const vector<int>& cvi = vi;
39 for (CIT it = cvi.begin (); it != cvi.end (); ++it)
40 cout << /*--*/*it << ' ';
41 cout << endl;
42 for (CRIT it = cvi.rbegin (); it!=cvi.rend(); ++it)
43 cout << *it << ' ';
44 cout << endl;
45 vector<string> vs;
46 vs.push_back ("beijing");
47 vs.push_back ("tianjin");
48 vs.push_back ("shanghai");
49 cout << *(vs.begin () + 2) << endl;
50 *const_cast<char*> ((vs.end () - 1)->c_str ())='S';
51 cout << *(vs.end () - 1) << endl;
52 vector<int> vi2 (10);
53 print (vi2);
54 vector<A> va (10);
55 for (vector<A>::const_iterator it = va.begin ();
56 it != va.end (); ++it)
57 cout << it->m_i << ' ';
58 cout << endl;
59 vector<int> vi3 (10, 8);
60 print (vi3);
61 vector<A> va2 (10, A (8));
62 for (vector<A>::const_iterator it = va2.begin ();
63 it != va2.end (); ++it)
64 cout << it->m_i << ' ';
65 cout << endl;
66 return 0;
67 }
5.size()/resize()/clear()/capacity()/reserve()
size() - 获取元素个数,而不是容量。
resize() - 增减元素的个数,增引发构造,减引发析构。如果在新增元素时发现当前容量不够,自动扩容。但是在减少元素时不会自动收缩容量。
clear() - 清空所有的元素,导致析构。同样不会自动收缩容量。
capacity() - 获取容量,以元素为单位。
reserve() - 手动扩容。新增部分不做初始化。
1 /*
2 *size() capacity()练习
3 */
4 #include <iostream>
5 #include <vector>
6 using namespace std;
7 void print (const vector<int>& vi) {
8 cout << "大小:" << vi.size () << endl;
9 cout << "容量:" << vi.capacity () << endl;
10 for (vector<int>::const_iterator it = vi.begin ();
11 it != vi.end (); ++it)
12 cout << *it << ' ';
13 cout << endl;
14 }
15 int main (void) {
16 vector<int> vi (5, 3);
17 print (vi);
18 vi.push_back (4);
19 print (vi);
20 vi[6] = 100;
21 cout << vi[6] << endl;
22 vi.push_back (5);
23 cout << vi[6] << endl;
24 vi.resize (12);
25 print (vi);
26 vi.resize (2);
27 print (vi);
28 vi.clear ();
29 print (vi);
30 vi.reserve (20);
31 print (vi);
32 cout << vi[19] << endl;
33 vi.reserve (5);
34 print (vi);
35 return 0;
36 }
6.insert()/erase()
insert()/erase() - 根据迭代器参数做插入和删除。
7.sort()/find()
sort()/find() - 全局泛型算法函数,排序(快速)和查找
1 /*
2 *sort() find()举例
3 */
4 #include <algorithm>
5 #include <vector>
6 #include "print.h"
7 template<typename iterator, typename type>
8 iterator find (iterator begin, iterator end,
9 const type& key) {
10 for (; begin != end; ++begin)
11 if (*begin == key)
12 break;
13 return begin;
14 }
15 bool cmpInt (const int& a, const int& b) {
16 return a > b;
17 }
18 class CmpInt {
19 public:
20 CmpInt (bool less = true) : m_less (less) {}
21 bool operator() (const int& a, const int& b) const{
22 return m_less ? (a < b) : (a > b);
23 }
24 private:
25 bool m_less;
26 };
27 int main (void) {
28 int ai[] = {10, 20, 30, 40, 50};
29 vector<int> vi (ai, &ai[5]);
30 print (vi.begin (), vi.end ());
31 vector<int>::iterator it = vi.begin ();
32 it = vi.insert (it + 1, 15);
33 print (vi.begin (), vi.end ());
34 ++++++it;
35 it = vi.erase (it);
36 print (vi.begin (), vi.end ());
37 cout << *it << endl; // 50
38 vi.insert (vi.begin (), 37);
39 vi.insert (vi.begin () + 2, 43);
40 vi.insert (vi.begin () + 4, 29);
41 vi.push_back (18);
42 vi.push_back (24);
43 print (vi.begin (), vi.end ());
44 sort (vi.begin (), vi.end ());
45 print (vi.begin (), vi.end ());
46 sort (vi.begin (), vi.end (),
47 /*cmpInt*/CmpInt (false));
48 print (vi.begin (), vi.end ());
49 it = ::find (vi.begin (), vi.end (), 18);
50 if (it == vi.end ())
51 cout << "没找到!" << endl;
52 else
53 cout << "找到了:" << *it << endl;
54 return 0;
55 }
1 /*文件名:print.h
2 *描述:泛型的print
3 */
4 #ifndef _PRINT_H
5 #define _PRINT_H
6 #include <iostream>
7 using namespace std;
8 template<typename iterator>
9 void print (iterator begin, iterator end) {
10 while (begin != end)
11 cout << *begin++ << ' ';
12 cout << endl;
13 }
14 #endif // _PRINT_H
8.类类型对象的向量
1)无参构造
2)拷贝构造
3)拷贝赋值
4)operator==:find
5)operator</operator基本类型/比较器
1 /*
2 *类类型对象的向量举例
3 * */
4 #include <vector>
5 #include <algorithm>
6 #include "print.h"
7 class A {
8 public:
9 A (int i = 0) : m_i (i) {
10 cout << "无参构造:" << this << endl;
11 }
12 A (const A& that) : m_i (that.m_i) {
13 cout << "拷贝构造:" << &that << "->" << this
14 << endl;
15 }
16 A& operator= (const A& that) {
17 cout << "拷贝赋值:" << &that << "->" << this
18 << endl;
19 if (&that != this)
20 m_i = that.m_i;
21 return *this;
22 }
23 ~A (void) {
24 cout << "析构函数:" << this << endl;
25 }
26 operator int& (void) {
27 return m_i;
28 }
29 /*
30 operator const int& (void) const {
31 return static_cast<int&> (
32 const_cast<A&> (*this));
33 }
34 */
35 bool operator== (const A& that) const {
36 return m_i == that.m_i;
37 }
38 /*
39 bool operator< (const A& that) const {
40 return m_i < that.m_i;
41 }
42 */
43 bool operator() (const A& a, const A& b) const {
44 return a.m_i < b.m_i;
45 }
46 private:
47 int m_i;
48 };
49 int main (void) {
50 cout << "---- 1 ----" << endl;
51 vector<A> va (3);
52 cout << "---- 2 ----" << endl;
53 va.push_back (A ());
54 cout << "---- 3 ----" << endl;
55 va.erase (va.begin ());
56 cout << "---- 0 ----" << endl;
57 va[0] = A (10);
58 va[1] = A (50);
59 va[2] = A (70);
60 va.push_back (A (60));
61 vector<A>::iterator it = find (va.begin (),
62 va.end (), A (70));
63 if (it == va.end ())
64 cout << "没找到!" << endl;
65 else
66 cout << "找到了:" << *it << endl;
67 // sort (va.begin (), va.end ());
68 sort (va.begin (), va.end (), va[0]);
69 print (va.begin (), va.end ());
70 return 0;
71 }
72
练习:编写程序读取m.dat中的电影票房记录,找出票房前十名,按票房从高到低的顺序写入另一文件中。
1 /*
2 *练习:编写程序读取m.dat中的电影票房记录,找出票房前十名,按票房从高到低的顺序写入另一文件中。
3 */
4 #include <iostream>
5 #include <fstream>
6 #include <vector>
7 #include <algorithm>
8 using namespace std;
9 class Movie {
10 public:
11 friend istream& operator>> (istream& is,
12 Movie& movie) {
13 return is >> movie.m_title >> movie.m_comp
14 >> movie.m_gross;
15 }
16 friend ostream& operator<< (ostream& os,
17 const Movie& movie) {
18 return os << movie.m_title << ' '
19 << movie.m_comp << ' ' << movie.m_gross;
20 }
21 bool operator< (const Movie& movie) const {
22 return gross () > movie.gross ();
23 }
24 private:
25 double gross (void) const {
26 string str (m_gross);
27 size_t pos = 0;
28 while ((pos = str.find_first_of ("$,", pos)) !=
29 string::npos)
30 str.erase (pos, 1);
31 return atof (str.c_str ());
32 }
33 string m_title;
34 string m_comp;
35 string m_gross;
36 };
37 bool read (const char* file, vector<Movie>& vm) {
38 ifstream ifs (file);
39 if (! ifs) {
40 perror ("打开票房文件失败");
41 return false;
42 }
43 Movie movie;
44 while (ifs >> movie)
45 vm.push_back (movie);
46 ifs.close ();
47 return true;
48 }
49 bool write (const char* file, const vector<Movie>& vm){
50 ofstream ofs (file);
51 if (! ofs) {
52 perror ("打开排行文件失败");
53 return false;
54 }
55 for (vector<Movie>::const_iterator it = vm.begin();
56 it != vm.end (); ++it)
57 ofs << *it << endl;
58 ofs.close ();
59 return true;
60 }
61 int main (int argc, char* argv[]) {
62 if (argc < 3) {
63 cerr << "用法:" << argv[0]
64 << " <票房文件> <排行文件>" << endl;
65 return -1;
66 }
67 vector<Movie> vm;
68 if (! read (argv[1], vm))
69 return -1;
70 sort (vm.begin (), vm.end ());
71 if (vm.size () > 10)
72 vm.resize (10);
73 if (! write (argv[2], vm))
74 return -1;
75 return 0;
76 }
四、双端队列(deque)
1.连续内存,下标访问和随机迭代,在首尾两端都可以进行高效的增删。
2.因为要维护首尾两端的开放性,因此双端队列和向量相比,其空间和时间复杂度要略高一些。
3.比vector多了push_front/pop_front,少了reserve。
1 /*
2 *deque举例
3 */
4 #include <deque>
5 #include <algorithm>
6 #include "print.h"
7 int main (void) {
8 deque<int> di;
9 di.push_back (24);
10 di.push_back (33);
11 di.push_front (18);
12 di.push_front (68);
13 di.insert (di.begin () + 2, 47);
14 print (di.begin (), di.end ()); // 68 18 47 24 33
15 di.pop_back ();
16 di.pop_front ();
17 di.erase (di.begin () + 1);
18 print (di.begin (), di.end ()); // 18 24
19 di.push_back (20);
20 sort (di.begin (), di.end ());
21 print (di.begin (), di.end ()); // 18 20 24
22 size_t size = di.size ();
23 for (size_t i = 0; i < size; ++i)
24 cout << di[i] << ' ';
25 cout << endl;
26 di.resize (10);
27 print (di.begin (), di.end ());
28 return 0;
29 }
五、列表(list)
front/back
push_front/pop_front
push_back/pop_back
insert/erase/remove
size
1.sort
2.unique - 将连续出现的相同元素唯一化。
23 35 35 35 60 12 35 35 99 35 22
| unique
V
23 35 60 12 35 99 35 22
3.splice - 将参数链表的部分或全部剪切到调用链表的特定位置。
void splice (
iterator pos,
list& lst);
list1.splice (pos, list2);
将list2中的全部数据剪切到list1的pos处。
void splice (
iterator pos,
list &lst,
iterator del);
将list2中del所指向数据剪切到list1的pos处。
void splice (
iterator pos,
list& lst,
iterator start,
iterator end );
将list2中start和end之间的数据剪切到list1的pos处。
4.merge - 合并
void merge (list& lst);
void merge (list& lst, Comp compfunction);
将有序的参数列表合并到调用列表中,保证合并后的调用列表依然有序。
注意:任何容器,在结构性修改之前获得的迭代器,有可能因为这种修改而失效,或者不能标识正确的位置,需要重新初始化
1 /*
2 *列表举例
3 */
4 #include <list>
5 #include "print.h"
6 int main (void) {
7 list<int> li;
8 li.push_back (34);
9 li.push_back (28);
10 li.push_back (34);
11 li.push_back (34);
12 li.push_back (55);
13 li.push_back (34);
14 print (li.begin (), li.end ());
15 li.unique ();
16 print (li.begin (), li.end ());
17 li.sort ();
18 print (li.begin (), li.end ());
19 li.unique ();
20 print (li.begin (), li.end ());
21 list<int> li2;
22 li2.push_front (100);
23 li2.push_front (200);
24 li2.push_front (300);
25 list<int>::iterator pos = li.begin ();
26 ++pos;
27 // li.splice (pos, li2);
28 list<int>::iterator start = li2.begin ();
29 ++start;
30 // li.splice (pos, li2, start);
31 list<int>::iterator end = li2.end ();
32 li.splice (pos, li2, start, end);
33 print (li.begin (), li.end ());
34 cout << li2.size () << endl;
35 return 0;
36 }
1 /*
2 *merge()练习
3 */
4 #include <list>
5 #include "../day12/print.h"
6 int main (void) {
7 int ai1[] = {13, 45, 67, 88, 92, 107};
8 int ai2[] = {22, 23, 37, 50, 69, 100, 109};
9 list<int> li1 (ai1, ai1 + 6);
10 list<int> li2 (ai2, ai2 + 7);
11 print (li1.begin (), li1.end ());
12 print (li2.begin (), li2.end ());
13 li1.merge (li2);
14 print (li1.begin (), li1.end ());
15 print (li2.begin (), li2.end ());
16 list<int>::iterator it = li1.begin ();
17 li1.insert (it, 1000);
18 it = li1.begin ();
19 li1.insert (it, 2000);
20 print (li1.begin (), li1.end ());
21 return 0;
22 }
六、堆栈
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;
};
1 /*
2 * 适配器练习- stack
3 *
4 * */
5 #include <iostream>
6 #include <stack>
7 #include <vector>
8 using namespace std;
9 int main (void) {
10 stack<string, vector<string> > ss;
11 ss.push ("吃饭");
12 ss.push ("喜欢");
13 ss.push ("偶");
14 while (! ss.empty ()) {
15 cout << ss.top ();
16 ss.pop ();
17 }
18 cout << endl;
19 return 0;
20 }
七、队列
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
1 /*
2 * 适配器练习- queue
3 * */
4 #include <iostream>
5 #include <queue>
6 #include <list>
7 using namespace std;
8 int main (void) {
9 queue<string, list<string> > qs;
10 qs.push ("我");
11 qs.push ("要");
12 qs.push ("吃");
13 qs.push ("饭");
14 while (! qs.empty ()) {
15 cout << qs.front ();
16 qs.pop ();
17 }
18 cout << endl;
19 return 0;
20 }
八、优先队列(priority_queue)
优者先出
底层容器:vector/deque/list,缺省deque
通过类型实参以比较器的形式定义比较规则
1 /*
2 * 适配器练习- priority queue
3 *
4 * */
5 #include <iostream>
6 #include <queue>
7 using namespace std;
8 class Student {
9 public:
10 Student (const string& name, float score) :
11 m_name (name), m_score (score) {}
12 void print (void) const {
13 cout << m_name << "," << m_score << endl;
14 }
15 bool operator< (const Student& student) const {
16 return m_score > student.m_score;
17 }
18 private:
19 string m_name;
20 float m_score;
21 };
22 class CmpInt {
23 public:
24 bool operator() (int a, int b) {
25 return a > b;
26 }
27 };
28 int main (void) {
29 // priority_queue<int> pqi;
30 priority_queue<int, deque<int>, CmpInt> pqi;
31 pqi.push (23);
32 pqi.push (12);
33 pqi.push (23);
34 pqi.push (27);
35 pqi.push (19);
36 while (! pqi.empty ()) {
37 cout << pqi.top () << ' ';
38 pqi.pop ();
39 }
40 cout << endl;
41 priority_queue<Student> pqs;
42 pqs.push (Student ("张飞", 65));
43 pqs.push (Student ("关羽", 60));
44 pqs.push (Student ("赵云", 85));
45 pqs.push (Student ("刘备", 95));
46 pqs.push (Student ("曹操", 25));
47 while (! pqs.empty ()) {
48 pqs.top ().print ();
49 pqs.pop ();
50 }
51 return 0;
52 }
九、映射(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升序的规则。
1 /*
2 * map练习
3 * */
4 #include <iostream>
5 #include <map>
6 using namespace std;
7 class Candidate {
8 public:
9 Candidate (const char* name = "") :
10 m_name (name), m_votes (0) {}
11 const string& name (void) const {
12 return m_name;
13 }
14 size_t votes (void) const {
15 return m_votes;
16 }
17 void vote (void) {
18 ++m_votes;
19 }
20 private:
21 string m_name;
22 size_t m_votes;
23 };
24 int main (void) {
25 map<char, Candidate> mc;
26 mc.insert (make_pair ('B', "赵云"));
27 mc.insert (pair<char, Candidate> ('A', "张飞"));//构造一个pair的对象放入map对象里
28 mc['D'] = "刘备";
29 mc['E'] = "曹操";
30 mc['C'] = "关羽";
31 mc['D'] = "黄忠";//因为key唯一且升序,所以这里会造成'D'不再与"刘备"形成映射
32 mc.insert (pair<char, Candidate> ('A', "马超"));//使用map的成员函数insert时候,insert判断出key已经与其他value形成映射,那么会忽略此次的insert
33 typedef map<char, Candidate>::iterator IT;
34 typedef map<char, Candidate>::const_iterator CIT;
35 for (size_t i = 0; i < 10; ++i) {
36 for (CIT it=mc.begin (); it != mc.end (); ++it)
37 cout << '(' << it->first << ')'
38 << it->second.name () << ' ';
39 cout << endl << "请投下宝贵的一票:" << flush;
40 char key;
41 cin >> key;
42 IT it = mc.find (key);
43 if (it == mc.end ()) {
44 cout << "此票作废!" << endl;
45 continue;
46 }
47 it->second.vote ();
48 }
49 CIT win = mc.begin ();
50 for (CIT it = mc.begin (); it != mc.end (); ++it){
51 cout << it->second.name () << "获得"
52 << it->second.votes () << "票。" << endl;
53 if (it->second.votes () > win->second.votes ())
54 win = it;
55 }
56 cout << "恭喜" << win->second.name () << "同学当选"
57 "为首席保洁员!" << endl;
58 return 0;
59 }
1 /*
2 *练习:编写程序,统计一个文本文件中每个单词出现的频率。按照词汇表的顺序打印输出。
3 *apple : 2
4 *beijing : 2
5 *c++ : 3
6 *...
7 * */
8 #include <iostream>
9 #include <fstream>
10 #include <map>
11 #include <cstring>
12 using namespace std;
13
14 class CmpStr {
15 public:
16 bool operator() (const string& a,
17 const string& b) const {
18 return strcasecmp (a.c_str (),
19 b.c_str ()) < 0;
20 }
21 };
22
23 int main (int argc, char* argv[]) {
24 if (argc < 2) {
25 cerr << "用法:" << argv[0] << " <文件>"<<endl;
26 return -1;
27 }
28 ifstream ifs (argv[1]);
29 if (! ifs) {
30 perror ("打开文件失败");
31 return -1;
32 }
33 map<string, int, CmpStr> msi;
34 string word;
35 while (ifs >> word)
36 ++msi[word];
37 ifs.close ();
38 for (map<string, int>::iterator it = msi.begin ();
39 it != msi.end (); ++it)
40 cout << it->first << " : " << it->second<<endl;
41
42 return 0;
43 }
十、集合
1 /*
2 *set练习
3 */
4 #include <iostream>
5 #include <set>
6 #include <fstream>
7 using namespace std;
8 int main (void) {
9 ifstream ifs ("test.txt");
10 set<string> ss;
11 string word;
12 while (ifs >> word)
13 ss.insert (word);
14 ifs.close ();
15 for (set<string>::iterator it = ss.begin ();
16 it != ss.end (); ++it)
17 cout << *it << endl;
18 cout << "共" << ss.size () << "个不同单词。"
19 << endl;
20 return 0;
21 }
十一、多重映射
key可重复,升序,迭代时key相同的元素相邻。
1 /*
2 *multimap练习
3 */
4 #include <iostream>
5 #include <map>
6 using namespace std;
7 int main (void) {
8 multimap<string, int> msi;
9 msi.insert (make_pair ("张飞", 100000));
10 msi.insert (make_pair ("赵云", 200000));
11 msi.insert (make_pair ("张飞", 300000));
12 msi.insert (make_pair ("关羽", 400000));
13 msi.insert (make_pair ("赵云", 500000));
14 msi.insert (make_pair ("关羽", 600000));
15 typedef multimap<string, int>::const_iterator CIT;
16 for (CIT it = msi.begin (); it != msi.end ();++it)
17 cout << it->first << " : " << it->second<<endl;
18 cout << "-------------" << endl;
19 for (CIT it = msi.begin (); it != msi.end();/*++it*/){
20 string key = it->first;
21 CIT end = msi.upper_bound (key);//upper_bound(key)成员函数返回和参数key相匹配的所有记录中最后一条记录的下一条记录的迭代器
22 int sum = 0;
23 for (; it != end; ++it)
24 sum += it->second;
25 cout << key << " : " << sum << endl;
26 // --it;
27 }
28 return 0;
29 }
十二、多重集合
1 /*
2 *multiset练习
3 */
4 #include <iostream>
5 #include <set>
6 using namespace std;
7 int main (void) {
8 const char* candidates[] = {
9 "张飞", "赵云", "关羽", "刘备", "曹操", NULL};
10 multiset<string> ms;
11 for (size_t i = 0; i < 10; ++i) {
12 for (size_t i = 0; candidates[i]; ++i)
13 cout << '(' << char ('A' + i) << ')'
14 << candidates[i] << ' ';
15 cout << endl << "请投下您庄严的一票:" <<flush;
16 char key;
17 cin >> key;
18 if (key < 'A' || 'E' < key) {
19 cout << "此票作废!" << endl;
20 continue;
21 }
22 ms.insert (candidates[key-'A']);
23 }
24 multiset<string>::iterator win = ms.begin ();
25 for (multiset<string>::iterator it = ms.begin ();
26 it != ms.end (); ++it) {
27 cout << *it << "获得" << ms.count (*it)
28 << "票。" << endl;
29 if (ms.count (*it) > ms.count (*win))
30 win = it;
31 it = ms.upper_bound (*it);
32 --it;
33 }
34 cout << "热烈祝贺" << *win << "当选垃圾长!"
35 << endl;
36 return 0;
37 }
十三、泛型算法
1.STL中包含60种泛型算法,其中包含23种非修改算法,如find,37种修改算法,如sort。
2.STL中的泛型算法多数都会迭代器实现对容器元素的访问。
3.STL中的泛型算法凡是涉及到比较大小的算法,都支持两种比较方案——“<”运算符和比较器函数对象。
4.除了STL中的容器以外,程序员也可以使自定义的容器,获得STL泛型算法的支持,只要改自定义类型能够支持此算法对迭代器的使用规则即可。
1 /*
2 *练习:假设现在有任意两个容器,请实现一个泛型的容器拷贝函数,用将一个容器中数据拷贝到另一个容器中。
3 */
4 #include <vector>
5 #include <deque>
6 #include <list>
7
8 template<typename iterator>
9 void print(iterator begin, iterator end)
10 {
11 while (begin != end) {
12 cout << *begin++ << ' ' << flush;
13 }
14 cout << endl;
15 return 0;
16 }
17
18 template<typename IT1, typename IT2>
19 void my_copy (IT1 begin, IT1 end, IT2 to) {
20 while (begin != end)
21 //*(to++) = *(begin++);
22 *to++ = *begin++;
23 }
24
25 int main (void) {
26 int arr1[5] = {10, 20, 30, 40, 50};
27 int arr2[5];
28 copy (arr1, arr1 + 5, arr2);
29 print (arr2, arr2 + 5);
30 vector<int> vec (5);
31 copy (arr1, arr1 + 5, vec.begin ());
32 print (vec.begin (), vec.end ());
33 deque<int> deq (5);
34 copy (vec.begin (), vec.end (), deq.begin ());
35 print (deq.begin (), deq.end ());
36 list<int> lst (5);
37 copy (deq.begin (), deq.end (), lst.begin ());
38 print (lst.begin (), lst.end ());
39 return 0;
40 }
来源:https://www.cnblogs.com/libig/p/4746729.html