(2011.09.25)《C++ Primer》第二部分学习笔记汇总——容器与算法

来源:互联网 发布:linux中查看日志文件 编辑:程序博客网 时间:2024/06/05 15:01
 

《C++ Primer》第二部分学习笔记汇总——容器与算法

 

《C++ Primer》 第09章学习笔记

第09章:容器与算法

 

@学习摘录072:顺序容器

——将单一类型元素聚集起来成为容器,然后根据位置来存储和访问这些元素,这就是顺序容器。

——vector  支持快速随机访问

——list     支持快速插入/删除

——deque  双端队列

 

@学习摘录073:顺序容器适配器

——适配器是根据原始的容器类型所提供的操作,通过定义新的操作接口,来适应基础的容器类型。

——stack                           后进先出(LIFO)栈

——queue                          先进先出(FIFO)队列

——priority_queue          有优先级管理的队列

 

第一节:顺序容器的定义(初始化)

 

@学习摘录074:新建一个容器初始化为另一个容器的副本

——vector <int> ivec;

——vector<int> ivec2(ivec);            // ok, ivec is vector<int>

——list<int> ilist(ivec);                      // error: ivec is not list<int>

——vector<double> dvec(ivec);    // error: ivec holds int now double

——将一个容器复制给另一个容器时,类型必须匹配:容器类型和元素类型都必须相同。

摘录有想074:

——这也就是说,容器复制的时候,只需考虑的是容器类型和元素类型,并不需要考虑原容器中的元素数量了,以前曾经想过这个问题。也会想一个问题,在定义新容器的时候,会不会出现溢出的情况呢?

 

@学习摘录075:初始化为一段元素的副本

——系统允许通过传递一对迭代器间接实现该功能。使用迭代器时,不要求容器类型相同,容器内的元素类型也可以不相同,只要它们相互兼容能进行转换即可。

——// initialize slist with copy of each element of svec

——list<string> slist(svec.begin(), svec.end() );

——// find midpoint in the vector

——vector<string>::iterator mid = svec.begin() + svec.size() / 2;

——// initialize front with first half of svec: The elements up to but note include *mid

——deque<string> front(svec.begin(), mid);

——// initialize back with second half of svec: The elements *mid through end of svec

——deque<string> back(mid, svec.end() );

摘录有想075:

——利用迭代器复制相当的方便,减少了很多限制,还可以不同类型的复制,只是也要考虑到一个方面,稳定性,如果需要隐式转换的地方还是少用的好。一段段的复制挺好的。同时,注意考虑它的区间是左闭右开的区间来的。

 

@学习摘录076:容器内元素的类型约束

——元素类型必须支持赋值运算。

——元素类型的对象必须可复制。

摘录有想076:

——这个问题,虽然不常发生,int型之类的内置类型不用考虑这个问题,而一些自己定义的类类型的话,真的得注意了。

 

@学习摘录077:容器的容器

——定义容器的容器时,有一个问题必须得注意的:

——vector< vector<string> > lines; // ok:space required between cblose>

——vector<vector<string>> lines; // error: >> treated as shift operator

——必须用空格隔开两个相邻的>符号,以示这是两个分开的符号。

——否则,系统会认为>>是单个符号,为右移操作符,并结果导致编译时的错误。

摘录有想077:

——网上的帖子看过很多人出现这个错,经典错误啊,就一个空格之差,让人看得纠结,写程序时,细节决定成败。

 

第二节:迭代器和迭代器范围

 

@学习摘录078:迭代器范围

——C++语言使用一对迭代器标记迭代器范围,这两个迭代器分别指向同一个容器中的两个元素或超出末端的下一位置。

——通常,这两个迭代器命名为first和last,或 beg和end,用于标记容器中的一段元素范围。

——该范围内的元素包括迭代器first指向的元素,以及从first开始一直到迭代器last指向的位置之前的所有元素。

——此类元素范围称“左闭合区间(left-inclusive interval) 表达式: [first, last]

摘录有想078:

——要记得啊,常常出现的字眼“超出末端的下一位置”。这一知识点,记住左闭区间是关键。

 

@学习摘录079:使用左闭合区间的编程意义

——左闭合区间有两个方便使用的性质,得记住:

——1. 当first 与last 相等时,迭代器范围为空;

——2. 当first与 last 不相等时,迭代器范围内至少有一个元素,而first指向该区间的第一个元素。

——while(first != last)

——{ // safe to use *first because we know there is at least one element

—— ++first;

——}

摘录有想079:

——我想:左闭合区间的使用,总的来说可以概括为三个字吧“安全性”。

 

第三节:顺序容器的操作

——每种顺序容器都提供了一组有用的类型定义以及以下操作:

——1. 在容器中添加元素

——2. 在容器中删除元素

——3. 设置容器的大小

——4. (如果有的话)获取容器内的第一个和最后一个元素。

 

@学习摘录080:在顺序容器中添加元素

——在容器中添加元素时,系统是将元素值复制到容器里。

摘录有想080:

——这令我想到了指针,使用指针,改变的是值,而地址不变。这个原理吧。

 

@学习摘录081:在容器中的指定位置添加元素

——看代码后,你懂的! s.insert(迭代器, 插入的东西); 新元素是插入在迭代器指向的位置之前。返回指向新添加元素的迭代器。

——s.insert(iter, element); // insert element just before iter

摘录有想081:

——考虑到有一种特例:push_back和push_front可以相当于iter为s.begin()和s.end() 时。

 

@学习摘录082:插入一段元素

——看代码后,你懂的!迭代器插入位置加上迭代器的前后位置构成的左闭合区间。

——string sarray[4] = {“quasi”, “samba”, “frollo”, “scar”}; 

——// insert all the element in sarray at end of slist

——slist.insert(slist.end(), sarray, sarray + 4);

 

@学习摘录083:关系操作符(比较大小)

——/*

——  ivec1: 1 3 5 7 9 12

——  ivec2: 0 2 4 6 8 10 12

——  ivec3: 1 3 9

——  ivec4: 1 3 5 7

——  ivec5: 1 3 5 7 9 12

——*/

—— // ivec 1 and ivec2 differ at element[0]: ivec1 greater than ivec2

——// ivec1 < ivec2 // false

——// ivec2 < ivec1 // true

——// ivec1 and ivec3 differ at element[2]: ivec1 less than ivec3

——ivec1 < ivec3 // true

——// all elements equal, but ivec4 has fewer elements, so ivec1 is greater than ivec4

——ivec1 < ivec4 // false

——ivec1 == ivec5 // true; each element equal and same number of elements

——ivec1 == ivec4 // false; ivec4 has fewer element

—— ivec1 != ivec4 // true; ivec4 has fewer elements than ivec1

摘录有想083:

——很明显,在容器中,比较大小;

——1.逐位对比,先比大小。 (大者为大)

——2.再比容器长度。(长者为大)

 

@学习摘录084:删除容器内所有的元素

——slist.clear(); // delete all the element within the container

——slist.erase(slist.begin(), slist.end() ); // equivalent

摘录有想084:

——要删除容器内所有的元素,可以调用clear函数,或将begin和end迭代器传递给erase函数。

 

@学习摘录085:容器中的赋值操作符

——赋值操作符首先删除其左操作数容器中的所有元素;

——然后将右操作数容器的所有元素插入到左边容器中;

——赋值后,左右两边的容器相等;

——赋值前可能两个容器长度不相等,但赋值后两个容器都具有右操作数的长度。

——c1 = c2; // replace contents of c1 with a copy of elements in c2

——// equivalent operation using erase and insert

——c1.erase(c1.begin(), c1.end() ); // delete all elements in c1

——c1.insert(c1.begin(), c2.begin(), c2.end() ); // insert c2

 

@学习摘录086:重设容器

——c.assign(b,e) // 重新设置c的元素:将迭代器b和e标记的范围内所有的元素复制到c中。b和e必须不是指向c中元素的迭代器。

——c.assign(n, t) // 将容器c重新设置为存储n个值为t 的元素

——// equivalent to: slist1.clear();

——// followed by slist1.insert(slist1.begin(), 10, “Hiya!”);

——slist1.assign(10, “Hiya!”); // 10 elements; each one is Hiya!

——执行了上述语句后,容器slist1有10个元素,每个元素的值都是Hiya!

摘录有想086:

——assign操作跟赋值操作符的操作原理差不多,都是先清空一个容器,然后再对已清空的容器进行插入操作。

 

@学习摘录087:交换容器

——swap操作实现交换两个容器内所有元素的功能。

——vector<string> svec1(10); // vector with 10 elements

——vector<string> svec2(24); // vector with 24 elements

——svec1.swap(svec2);

——执行swap后,容器svec1 中存储24个string类型的元素,而svec2则存储10个元素。

——关于swap的一个重要问题:

——1.该操作不会删除或插入任何元素;

——2.保证在常量时间内实现交换。

——3.由于容器内没有移动任何元素,因此迭代器不会失效。

摘录有想087:

——对此表示疑惑,为什么没有移动元素就没失效?它的原理是?猜测可能是变了变量的地址,其它一切无发生改变。

 

第四节:vector容器的自增长

 

@学习摘录088:vector的增长效率

——为了使vector容器实现快速的内存分配,其实际分配的容量要比当前所需的空间多一些。

——vector容器预留了这些额外的存储区,用于存放新添加的元素。

——于是,不必为每个新元素重新分配容器。

——所分配的额外内存容量的确切数目因库的实现不同而不同。

——比起每添加一个新元素就必须重新分配一次容器,这个分配策略带来显著的效率。

——事实上,其性能非常好,因此在实际应用中,比起list和deque容器,vector的增长效率通常会更高。

 

@学习摘录089:capacity成员

——弄清capacity(容量)与size(长度)的区别非常重要。

——size指容器当前拥有的元素个数;

——而capacity则指容器在必须分配新存储空间之前可以存储的元素总数。

——vector<int> ivec;

——// size should be zero; capacity is implementation defined

——cout << “ivec: size: “ << ivec.size()

——    << “ capacity: “ << ivec.capacity() << endl;

——// give ivec 24 elements

——for (vector<int>::size_type ix = 0; ix != 24; ++x)

——         ivec.push_back(ix);

——// size should be 24; capacity will be >= 24 and is implementation defined

——cout << “ivec: size: “ << ivec.size()

——  << “ capacity: “ << ivec.capacity() << endl;

——结果:

—— ivec: size: 0 capacity: 0

—— ivec: size: 24 capacity: 32

 

@学习摘录090:选择容器

——下面列举了四种选择容器的法则。

——1. 如果程序要求随机访问元素,则应使用vector或deque容器。

——2. 如果程序必须在容器的中间位置插入或删除元素,则应采用list容器。

——3. 如果程序不是在容器的中间位置,而是在容器首部或尾部插入或删除元素,则应采用deque容器。

——4. 如果只需在读取输入时在容器的中间位置插入元素,然后需要随机记问元素,则可考虑在输入时将元素读入到一个list容器,接着对此容器重新排序,使其适合顺序访问,然后将排序后的list容器复制到一个vector容器。

 

第六节:string类型

 

@学习摘录091:string类型的查找操作

——几乎所有的查找操作,返回的是string::size_type类型的值,以下标形式标记查找匹配所发生的位置;

——当查找没有匹配值,将返回名为string::npos的特殊值。

 

@学习摘录092:string类型的定义(一少部分)

——s.find(args)                      在s中查找args的第一次出现

——s.find_first_of(args) 在s中查找args的任意字符的第一次出现

——s.find_last_of(args)  在s中查找args的任意字符的最后一次出现

——s.find_first_not_of(args)  在s中查找第一个不属于args的字符

——s.find_last_not_of(args)  在s中查找最后一个不属于args的字符

摘录有想092:

——这几个定义,看上去,个人将其归纳两点:

——1. find操作可以分为第一次出现的关键字和最后次出现的关键字进行查找的标准。

——2. find操作可以分为查找属于args的字符和不属于args的字符。

 

 

《C++ Primer》 第10章学习笔记

第10章:关联容器

——关联容器(associative container)支持通过键来高效地查找和读取元素。

 

@学习摘录093:关联容器和顺序容器的本质差别

——关联容器通过键(key)存储和读取元素;

——顺序容器则通过元素在容器中的位置顺序存储和访问元素。

 

@学习摘录094:关联容器的主要特点

——关联容器的独特之处在于支持键的使用。

——关联容器根据键的次序排。

——在迭代遍历关联容器时,我们可以确保按键的顺序访问元素,而与元素在容器中的存放位置完全无关。(与插入顺序也无关)

 

@学习摘录095:关联容器的类型

——1.  map     关联数组;元素通过键来存储和读取

——2.  set           大小可变的集合,支持通过键实现的快速读取

——3.  multimap      支持同一个键多次出现的map类型

——4.  multiset       支持同一个键多次出现的set类型

 

@学习摘录096:两种基本关联容器的基本特点

——1. map的元素以键-值(key-value)对的形式组织。

—— 附:键,用作元素在map的索引。

——2. set仅包含一个键,能有效地支持关于某个键是否存在的查询。

 

@学习摘录097:四种关联容器需要注意的地方

——1. set 和 map类型的对象所包含的元素都具有不同的键,不允许为同一个键添加第二个元素。

——2. multimap和multiset 类型允许多个元素拥有相同的键,即用于一个键必须对应多个实例的情况下。(这两种类型不支持下标运算)

 

第一节:pair类型——#include <utility>

 

@学习摘录098:pair的创建与初始化

——pair<string, int> elem(“OK”, 110);  // holds a string and an int

——pair<string, vector<int> > line;    // holds string and vector<int>

 

@学习摘录099:pair对象的操作

——pair类,可直接访问其数据成员:成员都是公有的,分别命名为first和second

——pair< string, int> elem;

——elem.first = “OK”;

——elem.second = 3;

——cout << elem.first << elem.second; // 就这样,就给它们赋值了。

 

@学习摘录100:生成新的pair对象(make_pair)

——pair<string, string> next_auth;

——string first, last;

——while(cin >> first >> last)

——{

——// generate a pair from first and last

——next_auth = make_pair(first, last);

——// process next_auth..

——}

 

第三节:map类型——#include <map>

——map类型通常可理解为“关联数组”——通过键获取值,键-值相关联。

 

@学习摘录101:键类型的约束

——默认情况下标准库使用键类型定义 < 操作符来实现键的比较。

——所用的比较函数必须在键类型上定义严格弱排序(strict weak ordering)

摘录有想101:

——这也就是说,map<first, second> 中的first类型必须支持 < (小于)操作符。

 

@学习摘录102:map类定义的类型

——map<K, V>::key_type      在map容器中,用作索引的键的类型

——map<K, V>::mapped_type  在map容器中,键所关联的值的类型

——map<K, V>::value_type     一个pair类型,它的first元素具有key_type类型,second元素具有mapped_type类型

 

@学习摘录103:map类定义类型的访问方法及需要注意的地方

——当使用了map<K, V>::value_type时,该类型中的key_type类型是const性质,不可修改。

——当使用了map<K, V>::iterator时,该类型中的key_type类型是const性质,不可修改。

摘录有想103:

——即 map<string, int> ok; map<string, int>::value_type vt; map<string, int>::iterator = ok.begin();

——vt -> first; 只能读取,不能赋值。 iterator -> first也是只能读取不能赋值。

 

@学习摘录104:下标在map中的行为

——假如定义了一个名为ok的map<string, int>对象

——用下标操作ok[“in”] = 12 会有以下结果:

——当in存在,赋ok -> second值为12;

——当 in 不存在,新建(即插入) ”in” 元素并赋值为12.

摘录有想104:

——与顺序容器不同的一点是,用下标访问有可能会使map容器添加一个新的元素。

 

@学习摘录105:map中常用的insert操作

——m.insert(make_pair(“ok”, 12);

——m.insert(map<string, int>::value_type(“ok”, 1);

——m.inert(map<string, int>:: iterator a = m.begin(), map<string, int>::iterator b=++a );

——这三种操作,返回的都是void类型。

 

@学习摘录106:查找map中的元素

——m.find(k); 返回迭代器,存在,返回符合位置的迭代器,不存在,返回超出末端迭代器。

——m.count(k); 返回m中k的出现次数。

摘录有想106:

——count 操作根据map的性质,只能回返回0或1.

 

@学习摘录107:从map中删除元素

——// erase of a key returns number of element removed

—— if(word_count.erase(removal_word) )

——      cout << “ok: “ << removal_word << “ removed\n”;

—— else cout << “oops: “ << removal_word << “ not found! \n”;

——m.erase(k) 删除m中键为k的元素。返回size_type类型的值,表示删除的元素个数。

 

第五节:multimap和multiset类型

 

@学习摘录108:multimap和multiset类型元素的添加

——由于键不要求是唯一的,因此每次调用insert总会添加一个元素。

——multimap<string, string> authors;

——// adds first elemt with key a

—— authors.insert(make_pair( string(“a”), string(“b”) );

——ok: adds second element with key a

——authors.insert(make_pair(string(“a”), string(“c”) );

 

@学习摘录109:multimap和multiset类型元素的删除

——带有一个键参数的erase版本将删除拥有该键的“所有”元素,并返回删除元素的个数。

——multimap<string, string> ::size_type cnt = authors.erase( “a”);

 

@学习摘录110:multimap和multiset类型元素的查找――第一种方法

——直接见实例,当使用iter与find结合时,iter能保存所有find找到的键的结果。

// author we’ll look for

string search_item(“A”);

typedef multimap<string, string>::size_type sz_type;

sz_type entries = authors.count(search_item);

// get iterator to the first entry for this author

multimap<string, string>:: iterator iter = authors.find(search_item);

// loop through the number of entries there are for this author

for(sz_type cnt = 0; cnt != entries; ++cnt, ++iter)

   cout << iter -> second << end;  // print each title

——上例中,count函数求出某键出现次数,而find则返回一个迭代器,指向第一个正在查找的实例。

 

@学习摘录110:multimap和multiset类型元素的查找――第二种方法

——m.lower_bound(k)  返回一个迭代器,指向键不小于k的第一个元素

——m.upper_bound(k)  返回一个迭代器,指向键大于k的第一个元素

// definitions of authors and search_item as above

// beg and end denote range of elements for this author

typedef multimap<string, string>::iterator authors_it;

authors.it beg = authors.lower_bound(search_item);

authors.it end = authors.upper_bound(search_item);

// loop through the number of entries there are for this author

while( beg != end)

{

  cout << beg -> second << endl;   // print each title

  ++beg;

}

摘录有想110:

——这里利用了迭代器取得元素在multimap中的区间,能这样操作是因为,在multimap中,它的元素是以“键”的 < (小于)的顺序排序的

 

@学习摘录111:multimap和multiset类型元素的查找――第三种方法

——m.equal_range(k)  返回一个迭代器的pair对象,它的first成员等价于m.lower_bound(k),它的second成员等价于m.upper_bound(k);

——直接见实例:

typedef multimap<string, string>::iterator authors_it;

// definitions of authors and search_item as above

// pos holds iterators that denote range of elements for this key

pair<authors_it, authors_it> pos = authors.equal_range(search_item);

// loop through the number of entries there are for this author

while(pos.first != pos.second)

{

  cout << pos.first -> second << endl;  // print each title

  ++pos.first;

}

摘录有想111:

——这种使用方法,相当于第二种方法的简化,只是引用了一种pair类型。

 

@学习摘录112:*operator(解引用操作符在map、set、multimap、multiseet)

——在这些应用的时候,解引用操作符将生成一个value_type类型的值。

——对于map和multimap容器,value_type是pair类型。

 

 

《C++ Primer》 第11章学习笔记

第11章:泛型算法

——标准库提供一组不依赖特定的容器类型的算法作用在不同类型的容器和不同类型的元素上。

 

@学习摘录113:算法重要性质

——算法也许会改变存储在容器中的元素的值,也许会在容器内移动元素。

——但是,算法从不直接添加或删除元素。如果需要添加或删除元素,则必须使用容器操作。

 

第二节:初窥算法

—— #include <algorithm>   // 使用泛型算法

—— #include <numeric>    // 泛化的算术算法(generalized numeric algorithm)

 

@学习摘录114:迭代器实参类型

——大多数算法(前两个参数指定范围):

——通常:泛型算法都是在标记容器(或其他序列)内的元素范围的迭代器上操作的。

——标记范围的两个实参类型必须精确匹配,而迭代器本身必须标记一个范围:

——它们必须指向同一个容器中的元素(或者超出容器末端的下一位置),

——并且如果两者不相等,则第一个迭代器通过不断地自增,必须可以到达第二个迭代器。

——有些算法(带有两对迭代器参数)

——每对迭代器中,两个实参的类型必须精确匹配,但不要求两对之间的类型匹配。

——当元素存储在不同类型的序列中时,只要这两个序列中的元素可以比较即可。

 

第三节:再谈迭代器

——C++语言还提供了另外三种迭代器

 

@学习摘录115:三种容器的简单介绍

——插入迭代器(insert iterator):这类迭代器与容器绑定在一起,实现在容器中插入元素的功能。

——iostream迭代器(iostream iterator):这类迭代器可与输入或输出流绑定在一起,用于迭代遍历所关联的IO流。

——反向迭代器(reverse iterator):这类迭代器实现向后遍历,而不是向前遍历。

 

@学习摘录116:三种插入迭代器

——这里有三种插入器,其差别在于插入元素的位置不同:

——1. back_inserter, 创建使用push_back实现插入迭代器

——2. front_inserter, 使用push_front实现插入。

——3. insert, 使用insert实现插入操作。

 

@学习摘录117:三种inserter的综合应用

——在使用front_inserter时,元素始终在容器的第一个元素前面插入。

——使用inserter时,元素则在指定位置前面插入。

list<int> ilst, ilst2, ilst3;  // empty lists

// after this loop ilst contains: 3 2 1 0

for (list<int>::size_type i = 0; i != 4; ++i)

   ilst.push_front(i);

// after copy ilst2 contains: 0 1 2 3   // 与原容器顺序相反

copy(ilst.begin(), ilst.end(), front_inserter(ilst2));

// after copy, ilst3 contains: 3 2 1 0  // 与原容器顺序没变

copy(ilst.begin(), ilst.end(), inserter(ilst3, ilst3.begin() ));

 

@学习摘录118:iostream迭代器的构造函数

——istream_iterator<T> in(strm);  创建从输入流strm中读取T类型对象的istream_iterator对象

——istream_iterator<T> in;        istream_iterator 对象的超出末端迭代器

——ostream_iterator<T> in(strm);  创建将T类型的对象写到输出流strm的ostream_iterator对象

——ostream_iterator<T> in(strm, delim); 创建将T类型的对象写到输出流strm的ostream_iterator 对象,在写入过程中使用delim作为元素的分隔符。delim是以空字符结束的字符数组。

 

@学习摘录119:流迭代器的定义

istream_iterator<int> cin_in(cin);   // reads ints from cin

istream_iterator<int> end_of_stream;  // end iterator value

// writes Sales_items from the ofstream named outfile

// each element is followed by a space

ofstream outfile;

ostream_iterator<Sales_item> output(outfile, “ “);

 

@学习摘录120:istream_iterator对象上的操作

——下面的程序,衔从cin中读取int型数据,然后,使用eof作为结束符;

——在循环中,从cin中读取int型数据,并将读入的内容保存在vec中,再实现自增。

istream_iterator<int> in_iter(cin);   // read ints from cin

istream_iterator<int> eof;         // istream “end” iterator

// read until end of file, storing what was read in vec

while(in_iter != eof)

  // increment advances the stream to the next value

  // dereference reads next value from the istream

  vec.push_back(*in_iter++);

——也能直接用构造函数的方法新建对象:如下

istream_iterator<int> in_iter(cin);    // read ints from cin

istream_iterator<int> eof;          // istream “end” iterator

vector<int> vec(in_iter, eof);        // construct vec from an iterator range

 

@学习摘录121:ostream_iterator对象的使用

——可使用ostream_iterator对象将一个值序列写入流中,其操作的过程与使用迭代器在将一个组值逐个赋给容器中的元素相同。

// write one string per line to the standard output

ostream_iterator<string> out_iter(cout, “\n”);

// read strings from standard input and the end iterator

istream_iterator <string> in_iter(cin), eof;  // 此处会先输入第一次

// read until eof and write what was read to the standard output

while(in_iter != eof)

  // write value of in_iter to standard output

  // and then increment the iterator to get the next value from cin

  *out_iter++ = *in_iter++;    // 由于那次已输入了第一次,这次会再要求输入一次再显示

摘录有想121:

——程序经测试,每当输入一行字符后,则在下次输入另一行字符后显示上一行输入的字符。

——该程序可从while语句入手去想,逐行输入,放入in_iter,之后out_iter读取并显示。

——解引操作符能够使用数据。

 

@学习摘录122:与算法一起使用迭代器

——先看下面的例子:

istream_iterator<int> cin_it(cin);   // reads ints from cin

istream_iterator<int> end_of_stream;  // end iterator value

// initialize vec from the standard input:

vector<int> vec (cin_it, end_of_stream);

sort(vec.begin(), vec.end() );

// writes ints to cout using “ “ as the delimiter

ostream_iterator<int> output(cout, “ “);

// write only the unique elements in vec to the standard output

unique_copy(vec.begin(), vec.end(), output);

摘录有想122:

——以前总是看不懂这类程序,我想,现在看完这章的内容后,基本上还是理解了这类程序写的是什么了。

——前两行不断输入,直到遇到结束符,第三行,将输入的全部int逐个放入vec中;

——第四行,对容器进行排序。

——第五行,在每个cout 之间输入” “; 

——最后行,符合算法的格式,unique_copy算法,unique的“复制”版本,将输入范围内不重复的值输出,每个复制值后输出一个空格。

 

第四节:泛型算法的结构

——算法最基本的性质是需要使用的迭代器种类

 

@学习摘录123:根据对元素的操作将算法分为下面三种:

——1. 只读算法,不改变元素的值和顺序。

——2. 给指定元素赋新值的算法。

——3. 将一个元素的值移给另一个元素的算法。

 

@学习摘录124:算法的形参模式

——1. alg(beg, end, other parms);

——2. alg(beg, end, dest, other parms);

——3. alg(beg, end, dest, other parms);

——4.alg(beg, end, beg2, end2, other parms);

——注:dest形参是一个迭代器,用于指定存储输出数据的目标对象。

 

@学习摘录125:迭代器的分类

——迭代器可通过其所支持的操作来分类。

——1. 输入迭代器(input iterator):读,不能写;只支持自增运算

——2. 输出迭代器(output iterator):写,不能读;只支持自增运算

——3. 前向迭代器(forward iterator):读和写,只支持自增运算

——4. 双向迭代器(bidirectional iterator):读和写,支持自增和自减运算

——5. 随机访问迭代器(random-access iterator):读和写,支持完整的迭代器算术运算

 

 

原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 我生了爸爸孩子怎么办 三岁宝宝特别犟怎么办 孩子说老师打他怎么办 孩子在幼儿园不合群怎么办 孩与厌学不想学怎么办 1岁宝宝太活泼怎么办 3岁宝宝不爱看书怎么办 6岁不好好吃饭怎么办 二岁宝宝不吃饭怎么办 2岁半宝宝不爱吃饭怎么办 宝宝一岁了不爱吃饭怎么办 一岁多的宝宝不爱吃饭怎么办 小孩不吃饭还吐怎么办 一岁婴儿不吃饭怎么办 写字久了肩膀疼怎么办 6岁儿童不写字怎么办 孩子字写得丑怎么办 6岁儿童怕写字怎么办 高三学生上课困怎么办 高三学生压力大怎么办 数学会做的做错怎么办 脑子很笨反应慢怎么办 好学生考砸了怎么办 孩子写作业范愁怎么办 对粗心的孩子该怎么办 做计算题总出错怎么办 孩子字写得不好怎么办 3岁宝宝数学不好怎么办 十个月的宝宝拉肚子怎么办 刚生的宝宝拉肚子怎么办 我给兔子洗澡了怎么办 刚生的小狗脐带怎么办 宠物兔不想养了怎么办 兔子被打不动了怎么办 ai画板大小会变怎么办 和小孩生肖相冲怎么办 小孩和父母相冲怎么办 4岁宝宝抵抗力差怎么办 5岁儿童抵抗力差怎么办 格力小狗腿歪了怎么办 泰迪后腿骨折了怎么办