STL Tutorial Reference 读后总结

来源:互联网 发布:mac 电源线皮破了 编辑:程序博客网 时间:2024/05/05 18:17
把平常经常遇到,但是又没掌握的STL技术摘录下来,希望在以后能方便的索引。
  1. 解决两个空容器之间复制时空间问题:
  2. list<int> m_List;
  3. vector<int> m_Vector;
  4. for(int i=0; i<10; ++i)
  5. {
  6.     m_List.push_back(i);
  7. }
  8. copy(m_List.begin(),m_List.end(),m_Vector.begin());
  9. 此时,m_Vector中没有空间,不能复制
  10. 解决方案:
  11. 1. m_Vector.resize(m_List.size())
  12. 2. Vector<int> m_Vector(m_List.size());
  13. 3. copy(m_List.begin(),m_List.end(),back_inserter(m_Vector));
  14. //----------------------------------------------------------------------------------------------------
  15. 向容器插入元素另一种方法
  16. void print(string str)
  17. {
  18.     cout << str << endl;
  19. }
  20. vector<string> vec;
  21. copy(istream_iterator<string>(cin),istream_iterator<string>(),back_iterator(vec));
  22. for_each(vec.begin(),vec.end(),print);
  23. vector<string> vec((istream_iterator<string>(cin)),(istream_iterator<string>()));
  24. 注意:括号
  25. copy不需要自定义函数
  26. for_each需要自定义函数
  27. //------------------------------------------------------------------------------------------------------
  28. 打印容器中元素
  29. 1.
  30. copy (coll.rbegin(), coll.rend(), //source
  31. ostream_iterator<int> (cout," "));
  32. 2.
  33. template<class T> struct print : public unary_function<T, void>
  34. {
  35.     print(ostream& out) : os(out), count(0) {}
  36.     void operator() (T x) { os << x << ' '; ++count; }
  37.     ostream& os;
  38.     int count;
  39. };
  40. list<int> coll1;
  41. //insert elements from 1 to 9 into the first collection
  42. for (int i=1; i<=9; ++i) 
  43. {
  44.     coll1.push_back(i);
  45. }
  46. for_each(coll1.begin(),coll1.end(),print<int>(cout));
  47. cout << endl;
  48. // copy the elements of coll1 into coll2 by appending them
  49. vector<int> coll2;
  50. copy (coll1.begin(), coll1.end(), back_inserter(coll2)); //destination
  51. for_each(coll2.begin(),coll2.end(),print<int>(cout));
  52. //------------------------------------------------------------------------------------------------------
  53. unique_copy()只打印临近不相同的元素,若临近的元素有相同的,则只打印一个
  54. 示例:
  55. vector<string> vec;
  56. copy(istream_iterator<string>(cin),istream_iterator<string>(),back_inserter(vec));
  57. for_each(vec.begin(),vec.end(),print);
  58. cout << endl
  59. unique_copy(vec.begin(), vec.end(), ostream_iterator<string> (cout, "/n"));
  60. 输入:1 2 2 3 3 3 
  61. 输出:1 2 2 3 3 3
  62.         1 2 3
  63. //--------------------------------------------------------------------------------------------------------------
  64. Vector
  65. 删除含有值为val的元素
  66. vector<Elem> coll;
  67. ...
  68. coll.erase(remove(coll.begin(),coll.end(),val),coll.end());
  69. 删除指定元素
  70. vector<Elem> coll;
  71. ...
  72. vector<Elem>::iterator iter;
  73. iter=find(coll.begin(),coll.end(),val);
  74. if( iter!=coll.end() )
  75. {
  76.     coll.erase(pos);
  77. }
  78. //--------------------------------------------------------------------------------------------------------------
  79. List特殊函数示例:
  80. void PrintList(const list<int> &list1,const list<int> &list2)
  81. {
  82.     cout << "List1:" << endl;
  83.     copy(list1.begin(),list1.end(),ostream_iterator<int>(cout," "));
  84.     cout << endl;
  85.     cout << "List2:" << endl;
  86.     copy(list2.begin(),list2.end(),ostream_iterator<int>(cout," "));
  87.     cout << endl;
  88. }
  89. int main()
  90. {
  91.     //create two empty lists
  92.     list<int> list1, list2;
  93.     
  94.     //fill both lists with elements
  95.     for (int i=0; i<6; ++i) 
  96.     {
  97.         list1.push_back(i);
  98.         list2.push_front(i);
  99.     }
  100.     PrintList(list1,list2);
  101.     //insert all elements of list1 before the first element with value 3 of list2
  102.     //-find() returns an iterator to the first element with value 3
  103.     list2.splice(find(list2.begin(),list2.end(),3),list1);
  104.     PrintList(list1,list2);
  105.     //move first element to the end
  106.     list2.splice(list2.end(), list2, list2.begin()); // source position
  107.     PrintList(list1,list2);
  108.     cout << endl;
  109.     //sort second list, assign to list1 and remove duplicates
  110.     list2.sort();
  111.     list1 = list2;
  112.     list2.unique();
  113.     PrintList(list1, list2);
  114.     cout << endl;
  115.     //merge both sorted lists into the first list
  116.     list1.merge(list2);
  117.     PrintList(list1, list2);
  118.     system("pause");
  119.     return 0;
  120. }
  121. 输出结果:
  122. list1: 0 1 2 3 4 5
  123. list2: 5 4 3 2 1 0
  124. list1:
  125. list2: 5 4 0 1 2 3 4 5 3 2 1 0
  126. list1:
  127. list2: 4 0 1 2 3 4 5 3 2 1 0 5
  128. list1: 0 0 1 1 2 2 3 3 4 4 5 5
  129. list2: 0 1 2 3 4 5
  130. list1: 0 0 0 1 1 1 2 2 2 3 3 3 4 4 4 5 5 5
  131. list2:
  132. 分析:
  133. c.unique()      删除重复的元素
  134. c1.splice(pos,c2)       移动c2中的全部元素到c1前位置
  135. c1.splice(pos,c2,c2pos) 移动c2中c2pos前的元素到pos位置前
  136. c1.splice(pos,c2,c2beg,c2end)移动c2中的[c2beg,c2end)的元素到pos位置前
  137. c.sort()            按<排序
  138. c.sort(op)          按函数op的排序
  139. c1.merge(c2)        假设全部容器里的元素已经排序,移动所有c2元素到c1,仍然处于排序
  140. c1.merge(c2,op)     按op的排序,把c2移动到c1
  141. c.reverse()     反转
  142. //-------------------------------------------------------------------------------------------------------------
  143. 在set和multiset中,提供以下函数:
  144. count(elem)         返回含有elem元素的个数
  145. find(elem)      返回第一个elem元素的位置
  146. lower_bound(elem)   返回第一个>=elem元素的位置进行插入
  147. upper_bound(elem)   返回最后一个>elem元素的位置进行插入
  148. euqal_range()       返回第一个和最后一个==elem元素的位置进行插入
  149. set<int> c;
  150. c.insert(1);
  151. c.insert(2);
  152. c.insert(4);
  153. c.insert(5);
  154. c.insert(6);
  155. cout << "lower_bound(3): " << *c.lower_bound(3) << endl;
  156. cout << "lower_bound(3): " << *c.upper_bound(3) << endl;
  157. cout << endl;
  158. cout << "equal_range(3): " << *c.equal_range(3).first << endl;
  159. cout << "equal_range(3): " << *c.equal_range(3).second << endl;
  160. 输出结果:
  161. lower_bound(3): 4
  162. upper_bound(3): 4
  163. equal_range(3): 4 4
  164. set提供两种插入方式
  165. 1.pair<iterator,bool> insert(const value_type &elem);
  166. 2.iterator insert(iterator pos_hint,const valu_type &elem);
  167. pair结构的第二个成员代表插入成功的标志
  168. pair结构的第一个成员代表新插入元素的位置
  169. //-------------------------------------------------------------------------------------------------------------
  170. map和multimap
  171. 标准库没有提供他们的remove函数
  172. 插入元素有三种方法:
  173. 1.value_type
  174. map<string,float> coll;
  175. coll.insert(map<string,float>::value_type("ptt",22.3));
  176. 2.pair<>
  177. map<string,float> coll;
  178. //use no implcit conversion
  179. coll.insert(pair<string,float>("ptt",22.4));
  180. //use no implicit conversion
  181. cool.insert(pair<const string,float>("ptt",23.3));
  182. 3.make_pair()
  183. map<string,float> coll;
  184. coll.insert(make_pair("ppt",22.3));
  185. 插入并检查元素是否存在:
  186. map<string,float> coll;
  187. ...
  188. if (coll.insert(make_pair("otto",22.3)).second) 
  189. {
  190.     cout << "OK, could insert otto/22.3" << endl;
  191. }
  192. else 
  193. {
  194.     cout << "Oops, could not insert otto/22.3 "
  195.     << "(key otto already exists)" << endl;
  196. }
  197. 删除元素:
  198. map<string,float> coll;
  199. ...
  200. //remove all elements with the passed key
  201. coll.erase(key);
  202. 该版本的erase返回删除了的元素数目,且map类型时只能为0或1,而multimap则是所有
  203. 当删除元素会造成位置失效
  204. 故又两种方案解决删除元素:
  205. for(pos=coll.begin(); pos!=coll.end();)
  206. {
  207.     if( strcmp(pos->first.c_str(),"VAT")==0 )
  208.     {
  209.             1.//pos=coll.erase(pos);
  210.             2.//coll.erase(pos++);
  211.     }
  212.     else
  213.     {
  214.         ++pos;
  215.     }
  216. }
  217. //-----------------------------------------------------------------------------------------------------------
  218. iterator对象的使用
  219. vector<int> vec((istream_iterator<int>(cin)),(istream_iterator<int>()));
  220. copy(vec.begin(),vec.end(),ostream_iterator<int>(cout," "));
  221. advance()增加位置,iterator传递参数的值作为计量
  222. #include <iterator>
  223. void advance(InputIterator &pos,Dist n)
  224. distance()提供处理两个distance之间的数据
  225. #include <iterator>
  226. Dist distance (InputIterator pos1, InputIterator pos2)
  227. 注意:
  228. 1.返回值是iterator pos1和pos2之间的距离
  229. 2.两个iterator要指向同一个容器
  230. 3.如果iterator不是随机访问的iterator,则pos2必须能到达pos1,也就是说,必须为相同位置或者在pos1后
  231. 4.返回的类型是根据iterator的类型
  232. iter_swap()交换两个iterator的位置
  233. #include <algorithm>
  234. void iter_swap (ForwardIterator1 pos1, ForwardIterator2 pos2)
  235. 1.交换pos1和pos2的引用
  236. 2.iterator不一定要相同的类型,但是指向的值要能赋值
  237. //-----------------------------------------------------------------------------------------------------------
  238. rbegin()和rend()
  239. rbegin()和container::reverse_iterator(end())相同
  240. rend()和container::reverse_iterator(begin())相同
  241. base()把反向iterator转回正常iterator
  242. 例:
  243. 1 2 3 4 5 6 7 8 9
  244. list<int>::iterator pos;
  245. pos = find (coll.begin(), coll.end(), 5);
  246. cout << *pos;       //5
  247. //convert iterator to reverse iterator
  248. list<int>::reverse_iterator rpos(pos);
  249. cout << *rpos;      //4
  250. //convert reverse iterator back to normal iterator
  251. list<int>::iterator rrpos;
  252. rrpos = rpos.base();
  253. cout << *rrpos      //5
  254. //-------------------------------------------------------------------------------------------------------------
  255.                 Kinds of Insert Iterators
  256. Name        Class           Called Function         Creation
  257. Back inserter   back_insert_iterator    push_back (value)       back_inserter (cont)
  258. Front inserter  front_insert_iterator   push_front (value)      front_inserter (cont)
  259. General inserter    insert_iterator         insert (pos, value)         inserter (cont, pos)
  260. back iterator只适合于vector deque list和string 
  261. front iterator只适合于deque和list
  262. 使用前一定要初始化
  263. back_insert_iterator<vector<int> > iter(vec);
  264. back_inserter(vec)=44;
  265. back_inserter(vec)=55;
  266. //-------------------------------------------------------------------------------------------------------------
  267. istream_iterator的用法
  268. 两个istream iterators相等的条件是:
  269. 1.都是end_of_stream并且不能再读
  270. 2.都是用相同的输入流
  271. //create istream iterator that reads integers from cin
  272. istream_iterator<int> intReader(cin);
  273. //create end-of-stream iterator
  274. istream_iterator<int> intReaderEOF;
  275. /* while able to read tokens with istream iterator
  276. * - write them twice
  277. */
  278. while (intReader != intReaderEOF) 
  279. {
  280.     cout << "once: " << *intReader << endl;
  281.     cout << "once again: " << *intReader << endl;
  282.     ++intReader;
  283. }
  284. //--------------------------------------------------------------------------------------------------------------------
  285. 函数对象
  286. 函数形式:
  287. FunctionObjectType fo;
  288. ...
  289. fo(...);
  290. void fo() {
  291. statements
  292. }
  293. 函数对象形式:
  294. class FunctionObjectType
  295.  {
  296. public:
  297. void operator() 
  298. {
  299.     statements
  300. }
  301. };
  302. 使用函数对象比使用函数有三大优点:
  303. 1.函数对象可以有不同的实例,在不同的时间有不同的状态
  304. 2.函数对象都有自己的类型,所以可以用模板来提升类型的选择
  305. 3.函数对象通常情况下比函数指针速度更快,内联
  306. //--------------------------------------------------------------------------------------------------------------------
  307. generate_n和generate
  308. 第三个参数是函数对象
  309. generate_n把生成的值写到容器
  310. generate_n (back_inserter(coll),9,IntSequence(1));
  311. generate_n(ostream_iterator<int>(cout, "/n"), 100, rand);
  312. generate替换迭代器范围的值
  313. generate(V.begin(), V.end(), rand);
  314. vector<int> v (100);
  315. generate (v.begin(), v.end(), zero);
  316. //--------------------------------------------------------------------------------------------------------------------
  317. for_each的用法
  318. for_each拥有返回函数对象(唯一的一个algorithm成员)
  319. MeanValue mv = for_each (coll.begin(), coll.end(), MeanValue());
  320. template<class T> struct print : public unary_function<T, void>
  321. {
  322.   print(ostream& out) : os(out), count(0) {}
  323.   void operator() (T x) { os << x << ' '; ++count; }
  324.   ostream& os;
  325.   int count;
  326. };
  327. int main()
  328. {
  329.   int A[] = {1, 4, 2, 8, 5, 7};
  330.   const int N = sizeof(A) / sizeof(int);
  331.   print<int> P = for_each(A, A + N, print<int>(cout));
  332.   cout << endl << P.count << " objects printed." << endl;
  333. }
  334. //--------------------------------------------------------------------------------------------------------------------
  335. mem_fun_ref和mem_fun
  336. 当类没有重载operator()时候,调用成员函数需要使用mem_fun_ref或者mem_fun.
  337. 前者是直接引用,一般使用前者。当要传递参数的时候,需要使用bind2nd
  338. class Person 
  339. {
  340. private:
  341.     string name;
  342. public:
  343.     Person(string str):name(str)
  344.     {}
  345.     void print() const 
  346.     {
  347.         std::cout << name << std::endl;
  348.     }
  349.     void printWithPrefix (std::string prefix) const 
  350.     {
  351.         std::cout << prefix << name << std::endl;
  352.     }
  353. };
  354. vector<Person > coll;
  355. coll.push_back(Person("chenyu"));
  356. coll.push_back(Person("haha"));
  357. for_each (coll.begin(), coll.end(),mem_fun_ref(&Person::print));
  358. for_each (coll.begin(), coll.end(),bind2nd (mem_fun_ref (&Person::printWithPrefix),"person: "));
  359. mem_fun使用方法:
  360. struct B
  361.  {
  362.   virtual void print() = 0;
  363. };
  364. struct D1 : public B 
  365. {
  366.   void print() { cout << "I'm a D1" << endl; }
  367. };
  368. struct D2 : public B 
  369. {
  370.   void print() { cout << "I'm a D2" << endl; }
  371. };
  372. int main()
  373. {
  374.   vector<B*> V;
  375.   V.push_back(new D1);
  376.   V.push_back(new D2);
  377.   V.push_back(new D2);
  378.   V.push_back(new D1);
  379.   for_each(V.begin(), V.end(), mem_fun(&B::print));
  380. }
  381. //---------------------------------------------------------------------------------------------------------------------
  382. random_shuffle 
  383. 头文件 <algo.h>  有两个版本,使容器元素排列混乱(相对于sort)
  384. template <class RandomAccessIterator>
  385. void random_shuffle(RandomAccessIterator first, RandomAccessIterator last);
  386. template <class RandomAccessIterator, class RandomNumberGenerator>
  387. void random_shuffle(RandomAccessIterator first, RandomAccessIterator last,
  388.                     RandomNumberGenerator& rand)
  389. 示例:
  390. const int N = 8;
  391. int A[] = {1, 2, 3, 4, 5, 6, 7, 8};
  392. random_shuffle(A, A + N);
  393. copy(A, A + N, ostream_iterator<int>(cout, " "));
  394. // The printed result might be 7 1 6 3 2 5 4 8, 
  395. //  or any of 40,319 other possibilities.
  396. //---------------------------------------------------------------------------------------------------------------------
  397. itoa的使用
  398. template <class ForwardIterator, class T>void iota (ForwardIterator first, ForwardIterator last, T value);
  399. 填充vector,且值从0开始不断增大,结果为0,1,2...
  400. vector<int> a(100); // initial size 100 
  401. iota (a.begin(), a.end(), 0);
  402. 标准库没有提供itoa范围复制,如generate和generate_n,如下是自己提供的:
  403. template <class ForwardIterator, class T>
  404. void iota_n (ForwardIterator first, int n, T value)
  405. {  
  406.     for (int i = 0; i < n; i++)    
  407.         *first++ = value++;
  408. }
  409. //---------------------------------------------------------------------------------------------------------------------
  410. 反转字符串顺序(每个单词反转)
  411. const string delims(" /t,.;");
  412. string line;
  413. //for every line read successfully
  414. while (getline(cin,line)) 
  415. {
  416.     string::size_type begIdx, endIdx;
  417.     //search beginning of the first word
  418.     begIdx = line.find_first_not_of(delims);
  419.     //while beginning of a word found
  420.     while (begIdx != string::npos) 
  421.     {
  422.         //search end of the actual word
  423.         endIdx = line.find_first_of(delims, begIdx);
  424.         if (endIdx == string::npos) 
  425.         {
  426.             //end of word is end of line
  427.             endIdx = line.length();
  428.         }
  429.         //print characters in reverse order
  430.         for (int i=endIdx-1; i>=static_cast<int>(begIdx); --i)
  431.             cout << line [i];
  432.         cout << ' ';
  433.         //search beginning of the next word
  434.         begIdx = line.find_first_not_of (delims, endIdx);
  435.     }
  436. }
  437. 注意,使用 string::npos时,一定要用std::string::size_type作为类型
  438. string::npos定义为:static const size_type npos = -1;
  439. //---------------------------------------------------------------------------------------------------------------------
  440. string的构造函数
  441. 只有单个参数char *的版本'/0'才是一个特殊符号--终止符,在其他版本里就不是
  442. std::string s1("nico"); //initializes s1 with: 'n' 'i' 'c' 'o'
  443. std::string s2("nico",5) ; //initializes s2 with: 'n' 'i' 'c' 'o' '/0'
  444. std::string s3(5,'/0'); //initializes s3 with: '/0' '/0' '/0' '/0' '/0'
  445. s1.length() //yields 4
  446. s2.length() //yields 5
  447. s3.length() //yields 5
  448. std:: string s('x'); //ERROR
  449. std:: string s(1, 'x'); //OK, creates a string that has one character 'x'
  450. //---------------------------------------------------------------------------------------------------------------------
  451. IOStream库重要的操作符
  452. Manipulator         Class       Meaning
  453. endl            ostream         Outputs '/n' and flushes the output buffer
  454. ends            ostream         Outputs '/0'
  455. flush           ostream         Flushes the output buffer
  456. ws          istream         Reads and discards whitespaces
  457. 特别注意ws
  458. //---------------------------------------------------------------------------------------------------------------------
  459. set_union
  460. 具有两个重载函数:
  461. template <class InputIterator1, class InputIterator2, class OutputIterator>
  462. OutputIterator set_union(InputIterator1 first1, InputIterator1 last1,
  463.                          InputIterator2 first2, InputIterator2 last2,
  464.                          OutputIterator result);
  465. template <class InputIterator1, class InputIterator2, class OutputIterator,
  466.           class StrictWeakOrdering>
  467. OutputIterator set_union(InputIterator1 first1, InputIterator1 last1,
  468.                          InputIterator2 first2, InputIterator2 last2,
  469.                          OutputIterator result, 
  470.                          StrictWeakOrdering comp);
  471. set_union构造排序范围为[first1,last1)和[first2,last2),使其具有唯一性,返回值是output range的末尾
  472. inline bool lt_nocase(char c1, char c2) { return tolower(c1) < tolower(c2); }
  473. int main()
  474. {
  475.   int A1[] = {1, 3, 5, 7, 9, 11};
  476.   int A2[] = {1, 1, 2, 3, 5, 8, 13};  
  477.   char A3[] = {'a''b''B''B''f''H'};
  478.   char A4[] = {'A''B''b''C''D''F''F''h''h'};
  479.   const int N1 = sizeof(A1) / sizeof(int);
  480.   const int N2 = sizeof(A2) / sizeof(int); 
  481.   const int N3 = sizeof(A3);
  482.   const int N4 = sizeof(A4);
  483.   cout << "Union of A1 and A2: ";
  484.   set_union(A1, A1 + N1, A2, A2 + N2,
  485.             ostream_iterator<int>(cout, " "));
  486.   cout << endl 
  487.        << "Union of A3 and A4: ";
  488.   set_union(A3, A3 + N3, A4, A4 + N4, 
  489.             ostream_iterator<char>(cout, " "),
  490.             lt_nocase);
  491.   cout << endl;
  492. }

 

 

    

原创粉丝点击