当前位置:   article > 正文

7 STL

7 STL

1、STL简介

1.1基本概念

可复用利用的东西!

面向对象和泛型编程(模板)的 目的->提升复用性

为了建立数据结构和算法的一套标准->STL横空出世

  • STL(Standard Template Liberary)标准模板库
  • 广义分:容器、算法、迭代器
  • 容器和算法之间通过迭代器连接、STL几乎所有的代码均采用函数模板和类模板

1.2六大组件

  • 容器:各种数据结构,如vector、list、deque、map、set等由于数据存储。

       序列式排序:强调值的排序,序列式容器中的每个元素均有固定的位置。

       关联式排序:二叉树结构,各元素之间没有严格的物理的顺序关系。

  • 算法:各种算法,如:sort、find、copy、for_each等。
  • 迭代器:容器和算法连接桥梁。

       提供一种方法,使之间能够依次序访问某个容器所含的各个元素,而又无需暴露该容器的内部表示方式。每个容器都有自己专属的迭代器。类似于指针,可简单理解为指针。

迭代器种类:

种类功能支持运算
输入迭代器对数据的只读访问只读,支持++、==、!=
输出迭代器对数据的只写访问只写,支持++
前向迭代器读写操作,并能向前推进迭代器读写,支持++、==、!=
双向迭代器读写操作,并能向前和向后操作读写,支持++、--,
随机访问迭代器读写操作,可以以跳跃的方式访问任意数据,功能最强的迭代器读写,支持++、--、[n]、-n、<、<=、>、>=

常用的容器中迭代器种类为双向迭代器,和随机访问迭代器

  • 仿函数:作为算法的某种策略。
  • 适配器(配接器):一种用来修饰容器或者仿函数或迭代接口的东西。
  • 空间配置器:负责空间的配置与管理。

1.3容器、算法、迭代器案例(Vector)

创建、插入、遍历

1.3.1vector存放内置数据类型

案例代码:

  1. //.h
  2. #pragma once
  3. #include "iostream"
  4. #include"vector"
  5. #include "algorithm"
  6. class STL_Vector
  7. {
  8. public:
  9. void test_exp();
  10. };
  11. //.cpp
  12. #include "STL_Vector.h"
  13. using namespace std;
  14. void func(int val)
  15. {
  16. cout << val << endl;
  17. }
  18. void STL_Vector::test_exp()
  19. {
  20. //创建
  21. vector <int> v;
  22. //添加
  23. v.push_back(1);
  24. v.push_back(2);
  25. v.push_back(3);
  26. v.push_back(4);
  27. v.push_back(5);
  28. v.push_back(6);
  29. //遍历
  30. vector<int>::iterator it_begin = v.begin();
  31. vector<int>::iterator it_end = v.end();
  32. //方式一
  33. while (it_begin != it_end)
  34. {
  35. cout << *it_begin << endl;
  36. it_begin++;
  37. }
  38. //方式二
  39. for (vector<int>::iterator it = v.begin(); it != v.end(); it++)
  40. {
  41. cout << *it << endl;
  42. }
  43. //方式三
  44. for_each(v.begin(), v.end(), func);
  45. }
  46. //mian
  47. #include "iostream"
  48. using namespace std;
  49. #include "STL_Vector.h"
  50. int main()
  51. {
  52. STL_Vector sv = STL_Vector();
  53. sv.test_exp();
  54. system("pause");
  55. return 0;
  56. }

 运行结果:

1.3.2vector存放自定义数据类型及自定义对象指针

代码示例:

  1. //.h
  2. #pragma once
  3. #include "iostream"
  4. #include"vector"
  5. #include "algorithm"
  6. class STL_Vector
  7. {
  8. public:
  9. void test_exp();
  10. };
  11. //.cpp
  12. #include "STL_Vector.h"
  13. using namespace std;
  14. class Animal
  15. {
  16. public:
  17. Animal(int age,string name)
  18. {
  19. m_age = age;
  20. m_name = name;
  21. }
  22. public:
  23. int m_age;
  24. string m_name;
  25. };
  26. void func(int val)
  27. {
  28. cout << val;
  29. }
  30. void STL_Vector::test_exp()
  31. {
  32. //创建
  33. vector<Animal>v_p;
  34. vector<Animal *>v_point;
  35. //添加
  36. Animal a1(12,"僧面侯");
  37. Animal a2(12, "熊猫");
  38. Animal a3(12, "考拉");
  39. Animal a4(12, "袋鼠");
  40. v_p.push_back(a1);
  41. v_p.push_back(a2);
  42. v_p.push_back(a3);
  43. v_p.push_back(a3);
  44. v_point.push_back(&a1);
  45. v_point.push_back(&a2);
  46. v_point.push_back(&a3);
  47. v_point.push_back(&a4);
  48. //遍历
  49. for (vector<Animal>::iterator it = v_p.begin(); it != v_p.end(); it++)
  50. {
  51. cout << "年龄:" << it->m_age << "姓名:" << (*it).m_name << endl;
  52. }
  53. for (vector<Animal *>::iterator it = v_point.begin(); it != v_point.end(); it++)
  54. {
  55. cout << "年龄:" << (*it)->m_age << "姓名:" << (*it)->m_name << endl;
  56. }
  57. }
  58. //main
  59. #include "iostream"
  60. using namespace std;
  61. #include "STL_Vector.h"
  62. int main()
  63. {
  64. STL_Vector sv = STL_Vector();
  65. sv.test_exp();
  66. system("pause");
  67. return 0;
  68. }

运行结果:

1.3.3容器嵌套-有点二维数组的意思

代码示例:

  1. //.h
  2. #pragma once
  3. #include "iostream"
  4. #include"vector"
  5. #include "algorithm"
  6. class STL_Vector
  7. {
  8. public:
  9. void test_exp();
  10. };
  11. //.cpp
  12. #include "STL_Vector.h"
  13. using namespace std;
  14. class Animal
  15. {
  16. public:
  17. Animal(int age,string name)
  18. {
  19. m_age = age;
  20. m_name = name;
  21. }
  22. public:
  23. int m_age;
  24. string m_name;
  25. };
  26. void func(int val)
  27. {
  28. cout << val;
  29. }
  30. void STL_Vector::test_exp()
  31. {
  32. //创建
  33. vector<vector<string>> v_nest;
  34. vector<string> v_nest1;
  35. vector<string> v_nest2;
  36. vector<string> v_nest3;
  37. vector<string> v_nest4;
  38. //添加
  39. for (int i = 0; i < 5; i++)
  40. {
  41. if (i % 2 == 0)
  42. {
  43. v_nest1.push_back("我里个豆");
  44. v_nest2.push_back("我里个豆");
  45. v_nest3.push_back("我里个豆");
  46. v_nest4.push_back("我里个豆");
  47. }
  48. else
  49. {
  50. v_nest1.push_back("我里个乖");
  51. v_nest2.push_back("我里个乖");
  52. v_nest3.push_back("我里个乖");
  53. v_nest4.push_back("我里个乖");
  54. }
  55. }
  56. v_nest.push_back(v_nest1);
  57. v_nest.push_back(v_nest2);
  58. v_nest.push_back(v_nest3);
  59. v_nest.push_back(v_nest4);
  60. //遍历
  61. for (vector<vector<string>>::iterator it = v_nest.begin(); it != v_nest.end(); it++)
  62. {
  63. for (vector<string>::iterator itt = (*it).begin(); itt != (*it).end(); itt++)
  64. {
  65. cout << (*itt) ;
  66. }
  67. cout << endl;
  68. }
  69. }
  70. //mian
  71. #include "iostream"
  72. using namespace std;
  73. #include "STL_Vector.h"
  74. int main()
  75. {
  76. STL_Vector sv = STL_Vector();
  77. sv.test_exp();
  78. system("pause");
  79. return 0;
  80. }

2、常用容器

2.1string

本质:string是C++风格的字符串,string是一个类。

char *是一个指针,是C风格的字符串

string是一个类,封装了char*,管理和维护char*的容器

2.1.1string构造函数

  • 无参构造string();构造语句  string str;
  • 字符串初始化string(const char * str);
  • 拷贝构造string(const string& str);
  • n个字符构造string(int n,char c);

代码示例:

  1. //.h
  2. #pragma once
  3. #include "iostream"
  4. using namespace std;
  5. class string_
  6. {
  7. public:
  8. void test();
  9. };
  10. //.cpp
  11. #include "string_.h"
  12. #include "string"
  13. void string_::test()
  14. {
  15. //
  16. string str1;
  17. string str2 = "无语";
  18. string str3 = string(str2);
  19. string str4 = string(4, 'c');
  20. cout << "str1:" << str1 << endl;
  21. cout << "str2:" << str2 << endl;
  22. cout << "str3:" << str3 << endl;
  23. cout << "str4:" << str4 << endl;
  24. }
  25. int main()
  26. {
  27. string_ t;
  28. t.test();
  29. system("pause");
  30. return 0;
  31. }

运行结果:

 

2.1.2string的赋值操作

  • string& operator=(const char* s); //char*类型字符串 赋值给当前的字符串

  • string& operator=(const string &s); //把字符串s赋给当前的字符串

  • string& operator=(char c); //字符赋值给当前的字符串

  • string& assign(const char *s); //把字符串s赋给当前的字符串

  • string& assign(const char *s, int n); //把字符串s的前n个字符赋给当前的字符串

  • string& assign(const string &s); //把字符串s赋给当前字符串

  • string& assign(int n, char c); //用n个字符c赋给当前字符串

代码示例:

  1. //.h
  2. #pragma once
  3. #include "iostream"
  4. using namespace std;
  5. class string_
  6. {
  7. public:
  8. void test01();
  9. };
  10. //.cpp
  11. #include "string_.h"
  12. #include "string"
  13. using namespace std;
  14. //string & operator=(const char* s); //char*类型字符串 赋值给当前的字符串
  15. //
  16. //string& operator=(const string& s); //把字符串s赋给当前的字符串
  17. //
  18. //string& operator=(char c); //字符赋值给当前的字符串
  19. //
  20. //string& assign(const char* s); //把字符串s赋给当前的字符串
  21. //
  22. //string& assign(const char* s, int n); //把字符串s的前n个字符赋给当前的字符串
  23. //
  24. //string& assign(const string& s); //把字符串s赋给当前字符串
  25. //
  26. //string& assign(int n, char c); //用n个字符c赋给当前字符串
  27. void string_::test01()
  28. {
  29. string str1 = "无语考拉";
  30. string str2 = str1;
  31. string str3;
  32. str3 = 'a';
  33. string str4;
  34. str4.assign("无语拉拉");
  35. string str5;
  36. str5.assign(str4);
  37. string str6;
  38. str6.assign(4, 'c');
  39. cout << "str1 = " << str1 << endl;
  40. cout << "str2 = " << str2 << endl;
  41. cout << "str3 = " << str3 << endl;
  42. cout << "str4 = " << str4 << endl;
  43. cout << "str5 = " << str5 << endl;
  44. cout << "str6 = " << str6 << endl;
  45. }
  46. int main()
  47. {
  48. string_ t;
  49. t.test01();
  50. system("pause");
  51. return 0;
  52. }

运行结果:

 2.1.3string字符串拼接

  • string& operator+=(const char* str); //重载+=操作符

  • string& operator+=(const char c); //重载+=操作符

  • string& operator+=(const string& str); //重载+=操作符

  • string& append(const char *s); //把字符串s连接到当前字符串结尾

  • string& append(const char *s, int n); //把字符串s的前n个字符连接到当前字符串结尾

  • string& append(const string &s); //同operator+=(const string& str)

  • string& append(const string &s, int pos, int n);//字符串s中从pos开始的n个字符连接到字符串结尾

代码示例:

  1. //.h
  2. #pragma once
  3. #include "iostream"
  4. using namespace std;
  5. class string_
  6. {
  7. public:
  8. void test02();
  9. };
  10. //.cpp
  11. #include "string_.h"
  12. #include "string"
  13. using namespace std;
  14. //*`string& operator+=(const char* str); ` //重载+=操作符
  15. //* `string& operator+=(const char c); ` //重载+=操作符
  16. //* `string& operator+=(const string& str); ` //重载+=操作符
  17. //* `string& append(const char* s); ` //把字符串s连接到当前字符串结尾
  18. //* `string& append(const char* s, int n); ` //把字符串s的前n个字符连接到当前字符串结尾
  19. //* `string& append(const string& s); ` //同operator+=(const string& str)
  20. //* `string& append(const string& s, int pos, int n); `/ / 字符串s中从pos开始的n个字符连接到字符串结尾
  21. void string_::test02()
  22. {
  23. string str1 = "WC!";
  24. string str2;
  25. str2 += str1;
  26. string str3;
  27. str3 += str2;
  28. str3 += 'm';
  29. string str4;
  30. str4 += str2;
  31. str4 += "md";
  32. string str5;
  33. str5.append(str2);
  34. string str6;
  35. str6.append(str1, 2);
  36. str6.append(str2, 0, 2);
  37. cout << "str1 = " << str1 << endl;
  38. cout << "str2 = " << str2 << endl;
  39. cout << "str3 = " << str3 << endl;
  40. cout << "str4 = " << str4 << endl;
  41. cout << "str5 = " << str5 << endl;
  42. cout << "str6 = " << str6 << endl;
  43. }
  44. int main()
  45. {
  46. string_ t;
  47. t.test02();
  48. system("pause");
  49. return 0;
  50. }

运行结果:

2.1.4string查找和替换

  • int find(const string& str, int pos = 0) const; //查找str第一次出现位置,从pos开始查找

  • int find(const char* s, int pos = 0) const; //查找s第一次出现位置,从pos开始查找

  • int find(const char* s, int pos, int n) const; //从pos位置查找s的前n个字符第一次位置

  • int find(const char c, int pos = 0) const; //查找字符c第一次出现位置

  • int rfind(const string& str, int pos = npos) const; //查找str最后一次位置,从pos开始查找

  • int rfind(const char* s, int pos = npos) const; //查找s最后一次出现位置,从pos开始查找

  • int rfind(const char* s, int pos, int n) const; //从pos查找s的前n个字符最后一次位置

  • int rfind(const char c, int pos = 0) const; //查找字符c最后一次出现位置

  • string& replace(int pos, int n, const string& str); //替换从pos开始n个字符为字符串str

  • string& replace(int pos, int n,const char* s); //替换从pos开始的n个字符为字符串s

总结:

  • find查找是从左往后,rfind从右往左

  • find找到字符串后返回查找的第一个字符位置,找不到返回-1

  • replace在替换时,要指定从哪个位置起,多少个字符,替换成什么样的字符串(全换进去)

2.1.5string比较

  • 字符串比较是按字符的ASCII码进行对比

= 返回 0

> 返回 1

< 返回 -1

函数原型:

  • int compare(const string &s) const; //与字符串s比较

  • int compare(const char *s) const; //与字符串s比较

2.1.6string插入和删除

  • string& insert(int pos, const char* s); //插入字符串

  • string& insert(int pos, const string& str); //插入字符串

  • string& insert(int pos, int n, char c); //在指定位置插入n个字符c

  • string& erase(int pos, int n = npos); //删除从Pos开始的n个字符

插入和删除的起始坐标0开始!

2.1.7string截取子串

函数原型:

string substr(int pos = 0, int n = npos) const; //返回由pos开始的n个字符组成的字符串

代码示例:

  1. void string_::test04()
  2. {
  3. string str = "sefgsfsdfdsfg";
  4. string substr = str.substr(1, 5);
  5. cout << "substr:" << substr<<endl;
  6. //截取信息
  7. string str1 = "rwerwefgewf1313@163.cn";
  8. int pos = str1.find('@');
  9. cout << "emial:" << str1 << endl;
  10. string substr_email = str1.substr(0, pos);
  11. cout << "substr_email:" << substr_email;
  12. }

运行结果:

2.1.8string字符中字符获取与修改

string中单个字符存取方式有两种

  • char& operator[](int n); //通过[]方式取字符

  • char& at(int n); //通过at方法获取字符

代码示例:

  1. void string_::test03()
  2. {
  3. string str = "卧槽了,我去!";
  4. str[2] = 'a';
  5. for (int i = 0; i < str.size(); i++)
  6. {
  7. cout << str[i] ;
  8. }
  9. cout << endl;
  10. str.at(2) = 'a';
  11. for (int i = 0; i < str.size(); i++)
  12. {
  13. cout << str.at(i);
  14. }
  15. }

string字符串中单个字符存取有两种方式,利用 [ ] 或 at  

2.2vector容器 

2.2.1vector基本概念

又称单端数组

与数组的最大区别,数组静态的,vector可动态申请空间,采用的方式是动态扩展

即复制原数据到新开辟空间的上,并释放原空间

常用函数及迭代器:

vector容器是支持随机访问的迭代器

 2.2.2vector构造函数

  • vector<T> v; //采用模板实现类实现,默认构造函数

  • vector(v.begin(), v.end()); //将v[begin(), end())前闭后开区间中的元素拷贝给本身。

  • vector(n, elem); //构造函数将n个elem拷贝给本身。

  • vector(const vector &vec); //拷贝构造函数。

2.2.3vector赋值操作

  • vector& operator=(const vector &vec);//重载等号操作符

  • assign(beg, end); //将[beg, end)区间中的数据拷贝赋值给本身。

  • assign(n, elem); //将n个elem拷贝赋值给本身。

2.2.4vector容量

  • empty(); //判断容器是否为空,空返回为true,否则为false

  • capacity(); //容器的容量capacity >= size;

  • size(); //返回容器中元素的个数

  • resize(int num); //重新指定容器的长度为num,若容器变长,则以默认值(0)填充新位置。

                                  //如果容器变短,则末尾超出容器长度的元素被删除。

  • resize(int num, elem); //重新指定容器的长度为num,若容器变长,则以elem值填充新位置。

                                            //如果容器变短,则末尾超出容器长度的元素被删除

2.2.5 vector插入和删除

  • push_back(ele); //尾部插入元素ele

  • pop_back(); //删除最后一个元素

  • insert(const_iterator pos, ele); //迭代器指向位置pos插入元素ele

  • insert(const_iterator pos, int count,ele);//迭代器指向位置pos插入count个元素ele

  • erase(const_iterator pos); //删除迭代器指向的元素

  • erase(const_iterator start, const_iterator end);//删除迭代器从start到end之间的元素

  • clear(); //删除容器中所有元素

2.2.6vector数据获取

  • at(int idx); //返回索引idx所指的数据

  • operator[]; //返回索引idx所指的数据

  • front(); //返回容器中第一个数据元素

  • back(); //返回容器中最后一个数据元素

注意:是迭代器参数!

2.2.7vector互换

功能描述:

  • 实现两个容器内元素进行互换

函数原型:

  • swap(vec); // 将vec与本身的元素互换

实际用途:收缩内存空间

v.swap(v);

v的申请空间很大,但实际用的很少,内存浪费!于是vector<T> (v).swap(v);

vector<T> (v)为匿名对象,其占用内存和v一样,但申请空间和占用空间一致,最后再换给v,使得空间压缩,不浪费了!

2.2.8vector预留空间

功能描述:

  • 减少vector在动态扩展容量时的扩展次数

函数原型:

  • reserve(int len);//容器预留len个元素长度,预留位置不初始化,元素不可访问。

2.3deque容器

2.3.1deque基本概念和原理

功能:

  • 双端数组,可以对头端进行插入删除操作

deque与vector区别:

  • vector对于头部的插入删除效率低,数据量越大,效率越低

  • deque相对而言,对头部的插入删除速度回比vector快

  • vector访问元素时的速度会比deque快,这和两者内部实现有关

常用迭代器和函数:

deque内部工作原理:

deque内部有个中控器,维护每段缓冲区中的内容,缓冲区中存放真实数据

中控器维护的是每个缓冲区的地址,使得使用deque时像一片连续的内存空间

deque容器的迭代器也是支持随机访问的。

2.3.2deque构造函数

  • deque<T> deqT; //默认构造形式

  • deque(beg, end); //构造函数将[beg, end)区间中的元素拷贝给本身。

  • deque(n, elem); //构造函数将n个elem拷贝给本身。

  • deque(const deque &deq); //拷贝构造函数

注意:

//参数是const只读模式,则迭代器也应该变为只读迭代器

void printDeque(const deque<int>& d) 
{
    for (deque<int>::const_iterator it = d.begin(); it != d.end(); it++) {
        cout << *it << " ";

    }
    cout << endl;
}

2.3.4 deque赋值

  • deque& operator=(const deque &deq); //重载等号操作符

  • assign(beg, end); //将[beg, end)区间中的数据拷贝赋值给本身。

  • assign(n, elem); //将n个elem拷贝赋值给本身。

2.3.4deque大小获取、大小更改、判空

  • deque.empty(); //判断容器是否为空

  • deque.size(); //返回容器中元素的个数

  • deque.resize(num); //重新指定容器的长度为num,若容器变长,则以默认值(0)填充新位置。

    //如果容器变短,则末尾超出容器长度的元素被删除。

  • deque.resize(num, elem); //重新指定容器的长度为num,若容器变长,则以elem值填充新位置。

    //如果容器变短,则末尾超出容器长度的元素被删除。

注意:

deque没有capacity属性!

2.3.5deque插入与删除

  • push_back(elem); //在容器尾部添加一个数据

  • push_front(elem); //在容器头部插入一个数据

  • pop_back(); //删除容器最后一个数据

  • pop_front(); //删除容器第一个数据

指定位置操作:

pos是迭代器位置

  • insert(pos,elem); //在pos位置插入一个elem元素的拷贝,返回新数据的位置。

  • insert(pos,n,elem); //在pos位置插入n个elem数据,无返回值。

  • insert(pos,v.beg,v.end); //在pos位置插入迭代器[beg,end)区间的数据,无返回值。

  • clear(); //清空容器的所有数据

  • erase(beg,end); //删除迭代器[beg,end)区间的数据,返回下一个数据的位置。

  • erase(pos); //删除pos位置的数据,返回下一个数据的位置。

2.3.6数据获取

  • at(int idx); //返回索引idx所指的数据

  • operator[]; //返回索引idx所指的数据

  • front(); //返回容器中第一个数据元素

  • back(); //返回容器中最后一个数据元素

2.3.7排序

  • sort(iterator beg, iterator end) //对beg和end区间内元素进行排序

注意:#include ”algorithm“;

2.4容器案例

有5名选手,10个评委分别对每一名选手打分,去除最高分,去除评委中最低分,取平均分。

代码示例:

  1. //.h
  2. #pragma once
  3. #include "vector"
  4. #include "deque"
  5. #include "string"
  6. using namespace std;
  7. class player
  8. {
  9. public:
  10. string m_name;
  11. deque<float> m_scores;
  12. };
  13. class Exa_evaluate_score
  14. {
  15. public:
  16. Exa_evaluate_score();
  17. void eval(int index);
  18. void summarizing(int index);
  19. public:
  20. vector<player> m_p;
  21. };
  22. //.cpp
  23. #include "Exa_evaluate_score.h"
  24. #include "string"
  25. #include "deque"
  26. #include <iostream>
  27. #include "algorithm"
  28. using namespace std;
  29. Exa_evaluate_score::Exa_evaluate_score()
  30. {
  31. m_p.resize(10);
  32. }
  33. void Exa_evaluate_score::eval(int index)
  34. {
  35. cout << "请输入第" << index+1 << "位选手得分:" << endl;
  36. cout << "输入姓名:" ;
  37. string name;
  38. getline(cin, name);
  39. m_p[index].m_name= name;
  40. for (int j = 0; j < 10; j++)
  41. {
  42. cout << "第" << j + 1 << "位评委请对" << index+1 << "位选手打分:" << endl;
  43. float temp_score;
  44. cin >> temp_score;
  45. m_p[index].m_scores.push_back(temp_score);
  46. }
  47. }
  48. void Exa_evaluate_score::summarizing(int index)
  49. {
  50. sort(m_p[index].m_scores.begin(), m_p[index].m_scores.end());
  51. cout << "最低分为:" << m_p[index].m_scores.front() << endl;
  52. cout << "最高分为:" << m_p[index].m_scores.back() << endl;
  53. m_p[index].m_scores.pop_back();
  54. m_p[index].m_scores.pop_front();
  55. float sum = 0;
  56. for (deque<float>::iterator it = m_p[index].m_scores.begin(); it != m_p[index].m_scores.end(); it++)
  57. {
  58. sum += *it;
  59. }
  60. cout << "去除最低分最高分后平均分为:" <<(float)sum / m_p[index].m_scores.size() << endl;
  61. }
  62. int main()
  63. {
  64. Exa_evaluate_score e;
  65. for (int i = 0; i < 2; i++)
  66. {
  67. e.eval(i);
  68. e.summarizing(i);
  69. }
  70. system("pause");
  71. return 0;
  72. }

运行结果:

 

2.5stack 容器

2.5.1基本概念

FILO(First In Last Out)

2.5.2stack构造函数

  • stack<T> stk; //stack采用模板类实现, stack对象的默认构造形式

  • stack(const stack &stk); //拷贝构造函数

2.5.3stack赋值函数

  • stack& operator=(const stack &stk); //重载等号操作符

2.5.4stack出栈、入栈、取栈顶

  • push(elem); //向栈顶添加元素

  • pop(); //从栈顶移除第一个元素

  • top(); //返回栈顶元素

2.5.5stack判空、获取大小

  • empty(); //判断堆栈是否为空

  • size(); //返回栈的大小

2.6queue容器

2.6.1queue基本概念

FIFO(First In First Out)

常用函数:尾入头出

2.6.2queue构造函数

  • queue<T> que; //queue采用模板类实现,queue对象的默认构造形式

  • queue(const queue &que); //拷贝构造函数

2.6.7queue赋值操作

  • queue& operator=(const queue &que); //重载等号操作符

2.6.8queue入队、出队、获取队尾对头元素

  • push(elem); //往队尾添加元素

  • pop(); //从队头移除第一个元素

  • back(); //返回最后一个元素

  • front(); //返回第一个元素

2.6.9queue判空、获取大小

  • empty(); //判断堆栈是否为空

  • size(); //返回栈的大小

 2.7list容器

2.7.1list基本概念

双向循环链表:list容器的迭代器是双向迭代器,不支持随机访问!

由于链表的存储方式并不是连续的内存空间,因此链表list中的迭代器只支持前移和后移,属于双向迭代器  

list的优点:

  • 采用动态存储分配,不会造成内存浪费和溢出

  • 链表执行插入和删除操作十分方便,修改指针即可,不需要移动大量元素

list的缺点:

  • 链表灵活,但是空间(指针域) 和 时间(遍历)额外耗费较大

STL中List和vector是两个最常被使用的容器,各有优缺点

2.7.2 list构造函数

  • list<T> lst; //list采用采用模板类实现,对象的默认构造形式:

  • list(beg,end); //构造函数将[beg, end)区间中的元素拷贝给本身。

  • list(n,elem); //构造函数将n个elem拷贝给本身。

  • list(const list &lst); //拷贝构造函数。

2.7.3 list赋值操作

  • assign(beg, end); //将迭代器[beg, end)区间中的数据拷贝赋值给本身。

  • assign(n, elem); //将n个elem拷贝赋值给本身。

  • list& operator=(const list &lst); //重载等号操作符

2.7.4 list交换操作

swap(lst); //将lst与本身的元素互换。

注:不要求两个交换的list的数据个数相同!

2.7.5 list获取大小、判空、更改容量

  • size(); //返回容器中元素的个数

  • empty(); //判断容器是否为空

  • resize(num); //重新指定容器的长度为num,若容器变长,则以默认值填充新位置。

    //如果容器变短,则末尾超出容器长度的元素被删除。

  • resize(num, elem); //重新指定容器的长度为num,若容器变长,则以elem值填充新位置。 

                                        //如果容器变短,则末尾超出容器长度的元素被删除。

2.7.6 list插入与删除

  • push_back(elem);//在容器尾部加入一个元素

  • pop_back();//删除容器中最后一个元素

  • push_front(elem);//在容器开头插入一个元素

  • pop_front();//从容器开头移除第一个元素

  • insert(pos,elem);//在pos位置插elem元素的拷贝,返回新数据的位置。

  • insert(pos,n,elem);//在pos位置插入n个elem数据,无返回值。

  • insert(pos,beg,end);//在pos位置插入[beg,end)区间的数据,无返回值。

  • clear();//移除容器的所有数据

  • erase(beg,end);//删除[beg,end)区间的数据,返回下一个数据的位置。

  • erase(pos);//删除pos位置的数据,返回下一个数据的位置。

  • remove(elem);//删除容器中所有与elem值匹配的元素。

2.7.7 list 获取第一个元素、最后一个元素

list不支持随机访问,即无 [] ,at等随机访问的方法;

  • front(); //返回第一个元素。

  • back(); //返回最后一个元素。

 2.7.8 list反转和排序

  • reverse(); //反转链表

  • sort(); //链表排序 参数为一个回调函数,其中声明了排序次序即可更改默认 次序(从小到大)的次序。

L.sort(myCompare); //指定规则,从大到小      

bool myCompare(int val1 , int val2)
{
    return val1 > val2;
}                     

2.7.9 list排序案例

案例描述:将NuiMa自定义数据类型进行排序,NuiMa中属性有姓名、身份排名、薪资水平

排序规则:按照身份排名进行升序,如果身份排名相同按照薪资水平进行升序

代码示例:

  1. //.h
  2. #pragma once
  3. #include "string"
  4. #include "list"
  5. using namespace std;
  6. //牛马类
  7. class NiuMa
  8. {
  9. public:
  10. NiuMa(string name,int salary,int status)
  11. {
  12. m_name = name;
  13. m_status = status;
  14. m_salary = salary;
  15. };
  16. public:
  17. string m_name;
  18. int m_salary;
  19. int m_status;
  20. };
  21. class list_sort_niuma
  22. {
  23. public:
  24. list<NiuMa> m_NM;
  25. };
  26. //.cpp
  27. #include "list_sort_niuma.h"
  28. #include "iostream"
  29. bool sort_relu(NiuMa &nm1 , NiuMa &nm2)
  30. {
  31. if (nm1.m_status == nm2.m_status)
  32. {
  33. return nm1.m_salary > nm2.m_salary;
  34. }
  35. return nm1.m_status < nm2.m_status;
  36. }
  37. int main()
  38. {
  39. NiuMa nm1("小牛马1",5,1);
  40. NiuMa nm2("小牛马2", 50, 2);
  41. NiuMa nm3("小牛马3", 50, 2);
  42. NiuMa nm4("小牛马4", 500, 3);
  43. NiuMa nm5("小牛马5", 500, 1);
  44. NiuMa nm6("小牛马6", 5000, 1);
  45. list_sort_niuma lsn;
  46. lsn.m_NM.push_back(nm1);
  47. lsn.m_NM.push_back(nm2);
  48. lsn.m_NM.push_back(nm3);
  49. lsn.m_NM.push_back(nm4);
  50. lsn.m_NM.push_back(nm5);
  51. lsn.m_NM.push_back(nm6);
  52. cout << "排序前:" << endl;
  53. for (list<NiuMa>::iterator it = lsn.m_NM.begin(); it != lsn.m_NM.end(); it++)
  54. {
  55. cout << "姓名: " << it->m_name << " 社会地位排名: " << it->m_status
  56. << " 薪资水平: " << it->m_salary << endl;
  57. }
  58. lsn.m_NM.sort(sort_relu);
  59. cout << "排序后:" << endl;
  60. for (list<NiuMa>::iterator it = lsn.m_NM.begin(); it != lsn.m_NM.end(); it++)
  61. {
  62. cout << "姓名: " << it->m_name << " 社会地位排名: " << it->m_status
  63. << " 薪资水平: " << it->m_salary << endl;
  64. }
  65. system("pause");
  66. return 0;
  67. }

运行结果:

2.8set、multiset 容器

2.8.1set及multiset的基本概念和区别

简介所有的元素会被插入后自动进行排序

本质:关联式容器,底层二叉树实现

set与multiset区别:

  1. set不允许有重复元素
  2. multiset允许有重复元素

注:两个包含头文件,只需包含set即可,即#include ”set“;

2.8.2set构造函数

  • set<T> st; //默认构造函数:

  • set(const set &st); //拷贝构造函数

2.8.3set赋值操作

  • set& operator=(const set &st); //重载等号操作符

2.8.4set判空、获取大小、交换

  • size(); //返回容器中元素的数目

  • empty(); //判断容器是否为空

  • swap(st); //交换两个集合容器

2.8.5set插入与删除

  • insert(elem); //在容器中插入元素。

  • clear(); //清除所有元素

  • erase(pos); //删除pos迭代器所指的元素,返回下一个元素的迭代器。

  • erase(beg, end); //删除区间[beg,end)的所有元素 ,返回下一个元素的迭代器。

  • erase(elem); //删除容器中值为elem的元素。

2.8.6set查找与统计

  • find(key); //查找key是否存在,若存在,返回该键的元素的迭代器;若不存在,返回set.end();

  • count(key); //统计key的元素个数

2.8.7set、multiset的区别

  • set不可以插入重复数据,而multiset可以

  • set插入数据的同时会返回插入结果,表示插入是否成功

  • multiset不会检测数据,因此可以插入重复数据

2.8.8pair对组创建

成对出现的数据,利用对组可返回两个数据

对组创建方式:

pair<type,type> p (val1,val2);

pair<type,type> p = make_pair(val1,val2);

代码示例:

pair<string, int> p(string("Tom"), 20);

pair<string, int> p2 = make_pair("Jerry", 10);

2.8.9set排序

2.8.9.1内置数据类型排序

主要技术点:

  • 利用仿函数,可以改变排序规则

  • 注意:一定在插入之前就利用仿函数进行指定排序顺序

代码示例:

  1. #include "set"
  2. class MyCompare
  3. {
  4. public:
  5. bool operator()(int v1, int v2) {
  6. return v1 > v2;
  7. }
  8. };
  9. void test01()
  10. {
  11. set<int> s1;
  12. s1.insert(10);
  13. s1.insert(40);
  14. s1.insert(20);
  15. s1.insert(30);
  16. s1.insert(50);
  17. //默认从小到大
  18. for (set<int>::iterator it = s1.begin(); it != s1.end(); it++) {
  19. cout << *it << " ";
  20. }
  21. cout << endl;
  22. //指定排序规则
  23. set<int,MyCompare> s2;
  24. s2.insert(10);
  25. s2.insert(40);
  26. s2.insert(20);
  27. s2.insert(30);
  28. s2.insert(50);
  29. for (set<int, MyCompare>::iterator it = s2.begin(); it != s2.end(); it++) {
  30. cout << *it << " ";
  31. }
  32. cout << endl;
  33. }
  34. int main() {
  35. test01();
  36. system("pause");
  37. return 0;
  38. }
2.8.9.2自定义数据类型排序 

对于自定义数据类型,set必须指定排序规则才可以插入数据

代码示例:

  1. #include <set>
  2. #include <string>
  3. class Person
  4. {
  5. public:
  6. Person(string name, int age)
  7. {
  8. this->m_Name = name;
  9. this->m_Age = age;
  10. }
  11. string m_Name;
  12. int m_Age;
  13. };
  14. class comparePerson
  15. {
  16. public:
  17. bool operator()(const Person& p1, const Person &p2)
  18. {
  19. //按照年龄进行排序 降序
  20. return p1.m_Age > p2.m_Age;
  21. }
  22. };
  23. void test01()
  24. {
  25. set<Person, comparePerson> s;
  26. Person p1("刘备", 23);
  27. Person p2("关羽", 27);
  28. Person p3("张飞", 25);
  29. Person p4("赵云", 21);
  30. s.insert(p1);
  31. s.insert(p2);
  32. s.insert(p3);
  33. s.insert(p4);
  34. for (set<Person, comparePerson>::iterator it = s.begin(); it != s.end(); it++)
  35. {
  36. cout << "姓名: " << it->m_Name << " 年龄: " << it->m_Age << endl;
  37. }
  38. }
  39. int main() {
  40. test01();
  41. system("pause");
  42. return 0;
  43. }

2.9map、multimap容器

2.9.1map基本概念

简介:

  •  map中所有的元素都是pair
  • pair中第一个元素为key,起到索引作用,第二个元素为value
  • 所有的元素会根据元素key自动排序

本质:

  • map/multimap属于关联式容器,底层结构是用二叉树实现

优点:

  • 可以根据key值快速找到value值

map和multimap区别

  • map不允许容器中有重复key值元素

  • multimap允许容器中有重复key值元素

2.9.2map的构造和赋值

  • map<T1, T2> mp; //map默认构造函数:

  • map(const map &mp); //拷贝构造函数

  • map& operator=(const map &mp); //重载等号操作符

  1. void test01()
  2. {
  3. map<int,int>m; //默认构造
  4. m.insert(pair<int, int>(1, 10));
  5. m.insert(pair<int, int>(2, 20));
  6. m.insert(pair<int, int>(3, 30));
  7. printMap(m);
  8. map<int, int>m2(m); //拷贝构造
  9. printMap(m2);
  10. map<int, int>m3;
  11. m3 = m2; //赋值
  12. printMap(m3);
  13. }

2.9.3map判空、获取大小、交换

  • size(); //返回容器中元素的数目

  • empty(); //判断容器是否为空

  • swap(st); //交换两个集合容器

2.9.4map插入、删除

  • insert(elem); //在容器中插入元素。

  • clear(); //清除所有元素

  • erase(pos); //删除pos迭代器所指的元素,返回下一个元素的迭代器。

  • erase(beg, end); //删除区间[beg,end)的所有元素 ,返回下一个元素的迭代器。

  • erase(key); //删除容器中值为key的元素。

  1. void test01()
  2. {
  3. //插入
  4. map<int, int> m;
  5. //第一种插入方式-对组方式一
  6. m.insert(pair<int, int>(1, 10));
  7. //第二种插入方式-对组方式二
  8. m.insert(make_pair(2, 20));
  9. //第三种插入方式,不常用
  10. m.insert(map<int, int>::value_type(3, 30));
  11. //第四种插入方式
  12. //若key不存在则,会创建一个key为该值,value为默认参数的数据,不好
  13. //所以[]常用于根据key获取value
  14. m[4] = 40;
  15. printMap(m);
  16. //删除
  17. m.erase(m.begin());
  18. printMap(m);
  19. //按照key值删除
  20. m.erase(3);
  21. printMap(m);
  22. //清空
  23. m.erase(m.begin(),m.end());
  24. m.clear();
  25. printMap(m);
  26. }

2.9.5 map查找与统计

  • find(key); //查找key是否存在,若存在,返回该键的元素的迭代器;若不存在,返回set.end();

  • count(key); //统计key的元素个数

注意:

  • 查找 --- find (返回的是迭代器)

  • 统计 --- count (对于map,结果为0或者1)由于map不允许有重复的key对组!multimap而言就是具体的个数。

2.9.6map排序

  • map容器默认排序规则为 按照key值进行 从小到大排序,掌握如何改变排序规则

主要技术点:

  • 利用仿函数,可以改变排序规则

代码示例:

  1. #include <map>
  2. class MyCompare {
  3. public:
  4. bool operator()(int v1, int v2) {
  5. return v1 > v2;
  6. }
  7. };
  8. void test01()
  9. {
  10. //默认从小到大排序
  11. //利用仿函数实现从大到小排序
  12. map<int, int, MyCompare> m;
  13. m.insert(make_pair(1, 10));
  14. m.insert(make_pair(2, 20));
  15. m.insert(make_pair(3, 30));
  16. m.insert(make_pair(4, 40));
  17. m.insert(make_pair(5, 50));
  18. for (map<int, int, MyCompare>::iterator it = m.begin(); it != m.end(); it++) {
  19. cout << "key:" << it->first << " value:" << it->second << endl;
  20. }
  21. }
  22. int main() {
  23. test01();
  24. system("pause");
  25. return 0;
  26. }

总结:

  • 利用仿函数可以指定map容器的排序规则

  • 对于自定义数据类型,map必须要指定排序规则,同set容器

2.9.7map案例

案例描述:

  • 公司今天招聘了10个员工(ABCDEFGHIJ),10名员工进入公司之后,需要指派员工在那个部门工作

  • 员工信息有: 姓名 工资组成;部门分为:策划、美术、研发

  • 随机给10名员工分配部门和工资

  • 通过multimap进行信息的插入 key(部门编号) value(员工)

  • 分部门显示员工信息

代码示例:

  1. //.h
  2. #pragma once
  3. #include <iostream>
  4. #include <random>
  5. #include "string"
  6. #include "vector"
  7. #include "map"
  8. using namespace std;
  9. class employer
  10. {
  11. public:
  12. string m_Name;
  13. int m_DepId;
  14. float m_Salary;
  15. public:
  16. employer(string name)
  17. {
  18. m_Name = name;
  19. m_DepId = rand() % 3;
  20. // 创建一个随机数引擎
  21. std::random_device rd;
  22. std::mt19937 gen(rd());
  23. // 定义浮点数范围
  24. float lower_bound = 0.0f;
  25. float upper_bound = 100.0f;
  26. // 创建一个均匀分布的随机数生成器
  27. std::uniform_real_distribution<float> dist(lower_bound, upper_bound);
  28. // 生成随机浮点数
  29. m_Salary = dist(gen);
  30. }
  31. };
  32. class exp_map
  33. {
  34. public:
  35. vector<employer> m_emp;
  36. multimap<int, employer> m_DepMap;
  37. };
  38. //.cpp
  39. #include "exp_map.h"
  40. #include "iostream"
  41. using namespace std;
  42. #define CEHUA 0
  43. #define MEISHU 1
  44. #define YANFA 2
  45. void insert_exp(exp_map &em)
  46. {
  47. employer e1("A");
  48. employer e2("B");
  49. employer e3("C");
  50. employer e4("D");
  51. employer e5("E");
  52. employer e6("F");
  53. employer e7("G");
  54. employer e8("H");
  55. employer e9("I");
  56. employer e10("J");
  57. em.m_emp.push_back(e1);
  58. em.m_emp.push_back(e2);
  59. em.m_emp.push_back(e3);
  60. em.m_emp.push_back(e4);
  61. em.m_emp.push_back(e5);
  62. em.m_emp.push_back(e6);
  63. em.m_emp.push_back(e7);
  64. em.m_emp.push_back(e8);
  65. em.m_emp.push_back(e9);
  66. em.m_emp.push_back(e10);
  67. }
  68. void insert_multimap(exp_map& em)
  69. {
  70. for (vector<employer>::iterator it = em.m_emp.begin(); it != em.m_emp.end(); it++)
  71. {
  72. em.m_DepMap.insert(pair<int,employer>((*it).m_DepId,*it));
  73. }
  74. }
  75. void show_dep_emp(multimap<int, employer> &m)
  76. {
  77. //map会按照key进行排序,因此返回pos即第一个符合的位置,其后count个均为其满足条件的结果
  78. cout << "策划部门:" << endl;
  79. multimap<int, employer>::iterator pos = m.find(CEHUA);
  80. int count = m.count(CEHUA);
  81. int index = 0;
  82. for (; pos != m.end() && index < count; pos++, index++)
  83. {
  84. cout << "姓名: " << pos->second.m_Name << " 工资: " << pos->second.m_Salary << endl;
  85. }
  86. cout << "----------------------" << endl;
  87. cout << "美术部门: " << endl;
  88. pos = m.find(MEISHU);
  89. count = m.count(MEISHU); // 统计具体人数
  90. index = 0;
  91. for (; pos != m.end() && index < count; pos++, index++)
  92. {
  93. cout << "姓名: " << pos->second.m_Name << " 工资: " << pos->second.m_Salary << endl;
  94. }
  95. cout << "----------------------" << endl;
  96. cout << "研发部门: " << endl;
  97. //range是一个符合find条件的迭代器集合
  98. auto range = m.equal_range(YANFA);
  99. //range.first 指向范围的开始(第一个匹配元素),而 range.second 则指向范围的末尾(最后一个匹配元素的下一个位置)
  100. //auto 用于自动推导变量的类型。使用 auto 可以使编译器自动推断变量的类型,而不需要手动指定
  101. for (auto pos = range.first; pos != range.second; ++pos) {
  102. cout << "姓名: " << pos->second.m_Name << " 工资: " << pos->second.m_Salary << endl;
  103. }
  104. }
  105. int main()
  106. {
  107. exp_map em;
  108. insert_exp(em);
  109. insert_multimap(em);
  110. show_dep_emp(em.m_DepMap);
  111. system("pause");
  112. return 0;
  113. }

运行结果:

 

3、函数对象

3.1函数对象概念

概念:

  • 重载函数调用操作符的类,其对象常称为函数对象

  • 函数对象使用重载的()时,行为类似函数调用,也叫仿函数

本质:

函数对象(仿函数)是一个,不是一个函数

特点:

  • 函数对象在使用时,可以像普通函数那样调用, 可以有参数,可以有返回值

  • 函数对象超出普通函数的概念,函数对象可以有自己的状态

  • 函数对象可以作为参数传递

3.2函数对象的使用

1、函数对象在使用时,可以像普通函数那样调用, 可以有参数,可以有返回值

其实就是仿函数,本质是一个类重载了()运算符,然后通过匿名对象调用()。

2、函数对象可以有自己的状态

其实就是因为其本质是类,所以可以拥有成员变量即“自己的状态标识”

3、函数对象可以作为参数传递

其实就是因为其本质是类,则参数即为该类的对象实例!

3.3谓词

3.3.1谓词概念

  • 返回bool类型的仿函数被称为谓词
  • operator()重载()运算符,接受一个参数,那么叫一元谓词
  • operator()重载()运算符,接受两个参数,那么叫二元谓词

目前看与仿函数挂钩

3.4内建函数对象-可直接拿来用的仿函数

3.4.1概念

STL内建了一些函数对象

  • 算术仿函数
  • 关系仿函数
  • 逻辑仿函数

注意:

需要引入头文件 #include<functional>

3.4.2算术仿函数

仿函数原型:

  • template<class T> T plus<T> //加法仿函数

  • template<class T> T minus<T> //减法仿函数

  • template<class T> T multiplies<T> //乘法仿函数

  • template<class T> T divides<T> //除法仿函数

  • template<class T> T modulus<T> //取模仿函数

  • template<class T> T negate<T> //取反仿函数-一元仿函数,其余均为二元仿函数

  1. //negate
  2. void test01()
  3. {
  4. negate<int> n;
  5. cout << n(50) << endl;
  6. }
  7. //plus
  8. void test02()
  9. {
  10. plus<int> p;
  11. cout << p(10, 20) << endl;
  12. }

3.4.3关系仿函数

  • template<class T> bool equal_to<T> //等于

  • template<class T> bool not_equal_to<T> //不等于

  • template<class T> bool greater<T> //大于

  • template<class T> bool greater_equal<T> //大于等于

  • template<class T> bool less<T> //小于

  • template<class T> bool less_equal<T> //小于等于

  1. //伪代码
  2. class MyCompare
  3. {
  4. public:
  5. bool operator()(int v1,int v2)
  6. {
  7. return v1 > v2;
  8. }
  9. };
  10. //自己实现仿函数
  11. //sort(v.begin(), v.end(), MyCompare());
  12. //STL内建仿函数 大于仿函数
  13. sort(v.begin(), v.end(), greater<int>());

3.4.5逻辑仿函数

  • template<class T> bool logical_and<T> //逻辑与

  • template<class T> bool logical_or<T> //逻辑或

  • template<class T> bool logical_not<T> //逻辑非

逻辑仿函数实际应用较少,了解即可

4、STL-常用算法

4.1常用头文件

  • 算法主要是由头文件<algorithm> <functional> <numeric>组成。

  • <algorithm>是所有STL头文件中最大的一个,范围涉及到比较、 交换、查找、遍历操作、复制、修改等等

  • <numeric>体积很小,只包括几个在序列上面进行简单数学运算的模板函数

  • <functional>定义了一些模板类,用以声明函数对象。

4.2常用遍历算法

4.2.1for_each 很常用

功能:遍历容器元素

for_each(iterator beg, iterator end, _func);

// beg 开始迭代器

// end 结束迭代器

// _func 函数或者函数对象

4.2.2transform

功能:搬运容器到另一个容器中

transform(iterator beg1, iterator end1, iterator beg2, _func);

//beg1 源容器开始迭代器

//end1 源容器结束迭代器

//beg2 目标容器开始迭代器

//_func 函数或者函数对象,这可以对搬运的数据进行一些运算,实现在仿函数中

  1. //仿函数,不对搬运数据进行处理,直接返回
  2. class TransForm
  3. {
  4. public:
  5. int operator()(int val)
  6. {
  7. return val;
  8. }
  9. };

4.3常用查找算法

4.3.1find

功能:查找指定元素(内置类型、自定义类型),找到返回指定元素的迭代器,找不到返回结束迭代器end()

find(iterator beg, iterator end, value);

// 按值查找元素,找到返回指定位置迭代器,找不到返回结束迭代器位置

// beg 开始迭代器

// end 结束迭代器

// value 查找的元素

注意:利用find可以在容器中找指定的元素,返回值是迭代器

           对于自定义数据类型应该重载operator==,告诉如何对比查找。

  1. //重载==
  2. bool operator==(const Person& p)
  3. {
  4. if (this->m_Name == p.m_Name && this->m_Age == p.m_Age)
  5. {
  6. return true;
  7. }

4.3.2find_if

功能:按照条件查找元素

find_if(iterator beg, iterator end, _Pred);

// 按值查找元素,找到返回指定位置迭代器,找不到返回结束迭代器位置

// beg 开始迭代器

// end 结束迭代器

// _Pred 函数或者谓词(返回bool类型的仿函数)

4.3.3adjacent_find

功能:查找相邻重复元素

adjacent_find(iterator beg, iterator end);

// 查找相邻重复元素,返回相邻元素的第一个位置的迭代器

// beg 开始迭代器

// end 结束迭代器

4.3.4count

功能:统计元素个数

count(iterator beg, iterator end, value);

// 统计元素出现次数

// beg 开始迭代器

// end 结束迭代器

// value 统计的元素

注意:value也可以是自定义数据类型,需要在自定义数据类型重载operator==

  1. bool operator==(const Person & p)
  2. {
  3. if (this->m_Age == p.m_Age)
  4. {
  5. return true;
  6. }
  7. else
  8. {
  9. return false;
  10. }
  11. }

4.3.5count_if

功能:按条件统计元素个数

count_if(iterator beg, iterator end, _Pred);

// 按条件统计元素出现次数

// beg 开始迭代器

// end 结束迭代器

// _Pred 谓词

4.3.6binary_search

功能:查找指定元素是否存在

bool binary_search(iterator beg, iterator end, value);

// 查找指定的元素,查到 返回true 否则false

// 注意: 在无序序列中不可用,因为底层是二分查找

// beg 开始迭代器

// end 结束迭代器

// value 查找的元素

4.4常用排序算法

4.4.1sort 常用

功能:对容器内元素进行排序

sort(iterator beg, iterator end, _Pred);

// 按值查找元素,找到返回指定位置迭代器,找不到返回结束迭代器位置

// beg 开始迭代器

// end 结束迭代器

// _Pred 谓词

4.4.2random_shuffle

功能:洗牌、指定范围的元素打乱次序

random_shuffle(iterator beg, iterator end);

// 指定范围内的元素随机调整次序

// beg 开始迭代器

// end 结束迭代器

注意:用之前需要加种子,才能真实随机

随机种子:srand((unsigned int) time(NULL));

4.4.3merge

功能:两个容器元素合并,并存储到另一个容器中

merge(iterator beg1, iterator end1, iterator beg2, iterator end2, iterator dest);

// 容器元素合并,并存储到另一容器中

// 注意: 两个容器必须是有序的,记得给放入的容器resize扩容一下。

// beg1 容器1开始迭代器

// end1 容器1结束迭代器

// beg2 容器2开始迭代器

// end2 容器2结束迭代器

// dest 目标容器开始迭代器

4.4.4reverse

功能:容器内元素进行反转

reverse(iterator beg, iterator end);

// 反转指定范围的元素

// beg 开始迭代器

// end 结束迭代器

4.5常用拷贝喝替换函数

4.5.1copy

功能:容器内指定范围的元素拷贝到另一容器中

copy(iterator beg, iterator end, iterator dest);

// 按值查找元素,找到返回指定位置迭代器,找不到返回结束迭代器位置

// beg 开始迭代器

// end 结束迭代器

// dest 目标起始迭代器

4.5.2replace

功能:将容器内指定范围的旧元素替换为新的元素

replace(iterator beg, iterator end, oldvalue, newvalue);

// 将区间内旧元素 替换成 新元素

// beg 开始迭代器

// end 结束迭代器

// oldvalue 旧元素

// newvalue 新元素

4.5.3replace_if

功能:

将区间内满足条件的元素,替换成指定元素

replace_if(iterator beg, iterator end, _pred, newvalue);

// 按条件替换元素,满足条件的替换成指定元素

// beg 开始迭代器

// end 结束迭代器

// _pred 谓词

// newvalue 替换的新元素

4.5.4swap

功能:互换两个容器的元素

swap(container c1, container c2);

// 互换两个容器的元素

// c1容器1

// c2容器2

注意:两个容器数据类型必须相同

4.6常用算术生成算法

4.6.1accumulate

功能:计算区间内容器元素累计总和

accumulate(iterator beg, iterator end, value);

// 计算容器元素累计总和

// beg 开始迭代器

// end 结束迭代器

// value 起始值              一般为0

注意:accumulate使用时头文件注意是 numeric,这个算法很实用

4.6.2fill

功能:向容器中填充指定的元素

fill(iterator beg, iterator end, value);

// 向容器中填充元素

// beg 开始迭代器

// end 结束迭代器

// value 填充的值

4.7常用集合算法-交并差集

4.7.1set_intersectionn

功能:求两个容器的交集

set_intersection(iterator beg1, iterator end1, iterator beg2, iterator end2, iterator dest);

// 求两个集合的交集

// 注意:两个集合必须是有序序列

// beg1 容器1开始迭代器

// end1 容器1结束迭代器

// beg2 容器2开始迭代器

// end2 容器2结束迭代器

// dest 目标容器开始迭代器

注意:

  • 求交集的两个集合必须的有序序列

  • 目标容器开辟空间需要从两个容器中取小值

  • set_intersection返回值既是交集中最后一个元素的位置

遍历用返回的最后的迭代器itEnd.

  1. set_intersection(v1.begin(), v1.end(), v2.begin(), v2.end(), vTarget.begin());
  2. for_each(vTarget.begin(), itEnd, myPrint());
  3. cout << endl;

4.7.2set_union

功能:求并集

set_union(iterator beg1, iterator end1, iterator beg2, iterator end2, iterator dest);

// 求两个集合的并集

// 注意:两个集合必须是有序序列

// beg1 容器1开始迭代器

// end1 容器1结束迭代器

// beg2 容器2开始迭代器

// end2 容器2结束迭代器

// dest 目标容器开始迭代器

注意:

  • 求并集的两个集合必须的有序序列

  • 目标容器开辟空间需要两个容器相加

  • set_union返回值既是并集中最后一个元素的位置

4.7.3set_difference

功能:两个集合差集

set_difference(iterator beg1, iterator end1, iterator beg2, iterator end2, iterator dest);

// 求两个集合的差集

// 注意:两个集合必须是有序序列

// beg1 容器1开始迭代器

// end1 容器1结束迭代器

// beg2 容器2开始迭代器

// end2 容器2结束迭代器

// dest 目标容器开始迭代器

注意:

  • 求差集的两个集合必须的有序序列

  • 目标容器开辟空间需要从两个容器取较大值

  • set_difference返回值既是差集中最后一个元素的位置

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/AllinToyou/article/detail/64816
推荐阅读
相关标签
  

闽ICP备14008679号