码迷,mamicode.com
首页 > 编程语言 > 详细

Standard C++ Episode 11

时间:2015-08-21 07:01:59      阅读:184      评论:0      收藏:0      [点我收藏+]

标签:

一、标准模板库(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 &nbsp;* */
 8 #include <iostream>
 9 #include <fstream>
10 #include <map>
11 #include <cstring>
12 using namespace std;
13 
14 class CmpStr {
15 public:
16 &nbsp;&nbsp; &nbsp;bool operator() (const string& a,
17 &nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;const string& b) const {
18 &nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;return strcasecmp (a.c_str (),
19 &nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;b.c_str ()) < 0;
20 &nbsp;&nbsp; &nbsp;}
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 }

 

Standard C++ Episode 11

标签:

原文地址:http://www.cnblogs.com/libig/p/4746729.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!