STL 标准模版库
STL 从广义上分为容器 算法 迭代器
容器 (算法之间通过迭代器进行无缝链接)
STL几乎所有的代码都采用了模版类或者模版函数
STL六大组件
分别是容器 算法 迭代器 仿函数 适配器(配接器)空间配置器
容器 各种数据结构 vector list dequeue set map等用来存放数据
算法:sort find copy for_each
迭代器:扮演容器与算法之间的胶合板剂
仿函数:行为类似函数 可作为算法的某种策略。
适配器 一种用来修饰容器或者放函数或者迭代器接口的东西
空间配置 负责空间的配置与管理
容器:
STL容器就是将运用最广泛的一些数据结构实现出来
常用的数据结构:数组链表 树 栈 队列 集合 映射表
这些容器分为序列容器和关联容器两种
序列容器:强调值的排序 序列容器中的每个人元素有指定位置
关联容器:二叉树结构 各元素之间没有严格的物理上的顺序关系
算法:问题解法
有限的步骤 解决逻辑或者数学上的问题
算法分为质变算法和非质变算法
质变算法 是指运算过程中会更改区间内元素的内容。例如 拷贝 替换 删除
非质变算法: 是指运算过程中不会更改区间内的元素内容 例如查找 计数 遍历 寻找极质等
迭代器 容器和算法之间的粘合剂
提供一种方法 使之能够寻访某个容器所含的各种元素而又无需暴露该容器内部表示方式。
每个容器都有自己专属的迭代器
迭代器使用非常类似于指针 初学阶段我们可以先理解迭代器为指针。
vector
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
void printVector(int val) {cout << "val = " << val << endl;
}
void test86() {vector<int> v;v.push_back(1);v.push_back(4);v.push_back(7);v.push_back(2);v.push_back(5);vector<int>::iterator iBegin = v.begin();vector<int>::iterator iEnd = v.end();while (iBegin != iEnd) {cout << "iBegin = " << *iBegin << endl;iBegin++;}for (vector<int>::iterator it = v.begin();it != iEnd ; it++) {cout << "it = " << *it << endl;}for_each(v.begin(), v.end(), printVector);
}
int main(int argc, const char * argv[]) {// insert code here...std::cout << "Hello, World!\n";std::cout << "end!\n";//test84();test86();return 0;
}
自定义类型
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;class Person17 {// 属性 成员属性 成员变量//行为 成员函数 方法
private:string m_name;int m_age;
public:Person17(){}Person17(string name, int age) {this->m_name = name;this->m_age = age;}~Person17(){cout << "~Person17()" << endl;}string getName() {return m_name;}int getAge() {return m_age;}void personInfo() {std::cout << m_name << std::endl;}void setAge(int age) {if (age < 0 || age > 150) {std::cout << "age shu ru you wu" << std::endl;return;}m_age = age;}void setName(string name) {m_name = name;}
};
void printPerson17(Person17 val) {cout << "name = " << val.getName() << val.getAge() << endl;
}void test87() {vector<Person17> v;Person17 p("黎明",22);v.push_back(p);Person17 p1("刘德华",24);v.push_back(p1);Person17 p2("张学友",23);v.push_back(p2);Person17 p3("郭富城",25);v.push_back(p3);Person17 p4("古天乐",23);v.push_back(p4);for_each(v.begin(), v.end(), printPerson17);vector<Person17*> c;c.push_back(&p);c.push_back(&p1);c.push_back(&p2);c.push_back(&p3);c.push_back(&p4);for (vector<Person17 *>::iterator begin = c.begin(); begin != c.end() ; begin++) {cout << "Person17begin = " << (*begin)->getName() << (*begin)->getAge() << endl;}}
void printVector(int val) {cout << "val = " << val << endl;
}
void test86() {vector<int> v;v.push_back(1);v.push_back(4);v.push_back(7);v.push_back(2);v.push_back(5);vector<int>::iterator iBegin = v.begin();vector<int>::iterator iEnd = v.end();while (iBegin != iEnd) {cout << "iBegin = " << *iBegin << endl;iBegin++;}for (vector<int>::iterator it = v.begin();it != iEnd ; it++) {cout << "it = " << *it << endl;}for_each(v.begin(), v.end(), printVector);
}
int main(int argc, const char * argv[]) {// insert code here...std::cout << "Hello, World!\n";std::cout << "end!\n";//test84();test86();test87();return 0;
}
容器嵌套
void test88() {vector<vector<int>> array;vector<int> array1;array1.push_back(2);array1.push_back(5);array1.push_back(8);vector<int> array2;array2.push_back(3);array2.push_back(6);array2.push_back(9);vector<int> array3;array3.push_back(1);array3.push_back(4);array3.push_back(7);array.push_back(array1);array.push_back(array2);array.push_back(array3);for (vector<vector<int>>::iterator it = array.begin(); it != array.end(); it++) {vector<int> arr = (*it);for (vector<int>::iterator begin = arr.begin(); begin != arr.end(); begin++) {cout << *begin << endl;}}}
vector 基本概念
功能
vector 数据结构和数组非常相似 也称为单端数组
vector 与普通数组的区别
不同之处在于数组是静态空间 而vector可以动态扩展
动态扩展
并不是在原空间之后续新空间而是赵更大的空间 将原数据拷贝到新空间 释放原空间
vector容器的迭代器是支持随机访问的迭代器
vector构造函数
功能描述
创建vector容器
函数原型
vector<T> v; //采用模版实现类实现
vector(v.begin,v.end) 将【begin(),end())区间中的元素拷贝给本身
vector(n,elem) 构造函数将n个elem拷贝给本身
vector(const vector &vec)//拷贝构造函数
void test97() {vector<int> v;for (int i = 0 ; i < 10; i++) {v.push_back(i);}printVector(v);/// 区间构造vector<int>v2(v.begin(),v.end());printVector(v2);//n个elemvector<int>v3(10,100);printVector(v3);//拷贝构造vector<int>v4(v3);printVector(v4);}
赋值操作
void test98() {vector<int> v;for (int i = 0 ; i < 10; i++) {v.push_back(i);}printVector(v);vector<int>v2;v2 = v;printVector(v2);vector<int>v3;v3.assign(v.begin(), v.end());printVector(v3);vector<int>v4;v4.assign(10, 100);printVector(v4);}
vector容量和大小
功能:
对vector容器的容量和大小操作
函数原型
empty() 判断容器是否为空
capacity()容器的容量
size()返回容器中元素的个数
resize(int num) 重新指定容器的长度num若容器变长 则以默认值填充新位置
//如果容器变短 则末尾超出容器长度的元素被删除
resize(int num,elem) 重新指定容器的长度为num 若容器变长
则以elem值填充新位置
如果容器变短则末尾超出容器长度的元素被删除
void test99() {vector<int> v;for (int i = 0 ; i < 10; i++) {v.push_back(i);}printVector(v);cout << v.empty() << v.capacity() << v.size();// v.resize(15);printVector(v);// 重新指定大小 利用重载版本 可以指定默认填充值参数2v.resize(23,100);printVector(v);/// 重新指定的比原来短了 超出部分会删除v.resize(5);printVector(v);}
vector插入和删除
void test100() {vector<int> v;for (int i = 0 ; i < 10; i++) {v.push_back(i * 10);}printVector(v);v.pop_back();v.insert(v.begin(), 333);printVector(v);v.insert(v.begin(),3 ,1000);printVector(v);//删除第一个v.erase(v.begin());printVector(v);/// 清空v.erase(v.begin(),v.end());printVector(v);}
vector数据存取
功能描述:
对vector中的数据存取操作
函数原型
void test101() {vector<int> v;for (int i = 0 ; i < 10; i++) {v.push_back(i * 10);}for (int i = 0 ; i < 10; i++) {cout << v[i] << endl;}for (int i = 0 ; i < 10; i++) {cout << v.at(i) << endl;}cout << v.back() << v.front() << endl;}
vector 互换容器
实现两个容器内元素进行交换
函数原型
swap(vec)//将vec与本身的元素互换
void test102() {vector<int>v;for (int i = 0 ; i < 10000; i++) {v.push_back(i );}cout << v.capacity() << endl;cout << v.size()<< endl;;v.resize(2);cout << v.capacity() << endl;cout << v.size()<< endl;;//使用swap收缩内存 // vector<int>(v) 匿名对象vector<int>(v).swap(v);cout << v.capacity() << endl;cout << v.size()<< endl;;
}
可以使两个容器互换 可以达到实用的收缩内存的效果
vector 预留空间
减少vector在动态扩展容量时的扩展次数
函数原型
reserve(int len) // 容器预留len个元素长度 预留位置不初始化 元素不可访问
void test103() {vector<int>v;int num = 0; //记录空间分配次数int *p = NULL;for (int i = 0 ; i < 10000; i++) {v.push_back(i );if (p != &v[0]) {p = &v[0];num++;}}cout << v.capacity() << "num =" << num << endl;cout << v.size()<< endl;;vector<int>v2;int num1 = 0;//记录空间分配次数int *p1 = NULL;// 利用reserve预留空间v2.reserve(10000);for (int i = 0 ; i < 10000; i++) {v2.push_back(i );if (p1 != &v2[0]) {p1 = &v2[0];num1++;}}cout << v2.capacity() << "num1 =" << num1 << endl;cout << v2.size()<< endl;;}16384num =15
10000
10000num1 =1
10000
数据量很大使用reserve预留空间
deque容器
功能
双端数组 可以对头端进行插入删除操作
deque和vector区别
vector对于头部的插入删除效率低 数据量越大 效率越低
deque 相对而言对头部的插入删除速度会比vector快
vector访问元素时速度会比deque快 这和两者内部实现有关
工作原理
deque内部由个中控器维护每段缓冲区的内容 缓冲区中存放真实数据
中控器维护的是每个缓冲区的地址 使得使用deque时像一片连续的内存空间
deque容器的迭代器支持随机访问
构造函数
功能
deque容器构造
函数原型
deque<T> deqT; 默认构造
deque(begin,end) 构造函数将begin和end区间中的元素拷贝给本身
deque(n,elem)构造函数将n个elem拷贝给本身
deque(const deque &deq)//拷贝构造函数
void printdeque(const deque<int> &d)
{//const_iterator 只读迭代器for (deque<int>::const_iterator begin = d.begin(); begin != d.end(); begin++) {cout << *begin << endl;}}
void test104() {deque<int> d1;for (int i = 0 ; i < 10; i++) {d1.push_back(i);}printdeque(d1);deque<int> d2(d1.begin(),d1.end());printdeque(d2);deque<int> d3(10,100);printdeque(d3);deque<int>d4(d3);printdeque(d4);}
赋值操作
void test105() {deque<int> d1;for (int i = 0 ; i < 10; i++) {d1.push_back(i);}printdeque(d1);deque<int> d2;d2 = d1;printdeque(d2);deque<int> d3;d3.assign(d1.begin(),d1.end());printdeque(d3);deque<int> d4;d4.assign(10,100);printdeque(d4);}
大小操作
void test106() {deque<int> d1;for (int i = 0 ; i < 10; i++) {d1.push_back(i);}cout << d1.size() << endl;cout << d1.empty() << endl;printdeque(d1);d1.resize(15,1);cout << d1.size() << endl;printdeque(d1);d1.resize(5,1);printdeque(d1);}
deque 插入和删除
void test107() {deque<int> d1;d1.push_back(111);d1.push_back(222);d1.push_front(1);d1.push_front(12);printdeque(d1);d1.pop_back();printdeque(d1);d1.pop_front();printdeque(d1);d1.insert(d1.begin(), 666);d1.insert(d1.begin(), 2,3345);printdeque(d1);deque<int> d2;d2.push_back(21);d2.push_back(22);d2.push_back(24);d2.push_back(25);d1.insert(d1.begin(),d2.begin(),d2.end());cout<<endl;printdeque(d1);cout<<endl;deque<int>::iterator it = d1.begin();it++;d1.erase(it);printdeque(d1);cout<<endl;d1.erase(d1.begin() + 2,d1.end());printdeque(d1);cout<<endl;d1.clear();printdeque(d1);}
deque 数据存取
对deque中的数据存取操作
函数原型
void test108() {deque<int> d1;d1.push_back(111);d1.push_back(222);d1.push_front(1);d1.push_front(12);cout << d1[2] << endl;cout << d1.at(0) << endl;cout << d1.front() << endl;cout << d1.back() << endl;}
排序操作
void test109() {deque<int> d1;d1.push_back(111);d1.push_back(222);d1.push_front(1);d1.push_front(12);printdeque(d1);// 默认是从小到大sort(d1.begin(), d1.end());printdeque(d1);
}
string 基本概念
string是c++风格的字符串 它是一个类
string 和char *区别
string 类内部封装了很多成员方法
例如 查找 find 拷copy 删除delete 替换replace 插入 insert
string 管理char *所分配的内存 不用担心复制越界和取值越界等 由类内部进行负责
string 构造函数
string() // 创建空字符串
string(const char *s) 使用字符串s初始化
string(const string& str) 使用一个string对象初始化另一个字符串对象
string(int n,char c) // 使用n个字符c初始化
void test89() {string s1; //默认构造const char *str = "hello world";string s2(str);cout << "s2=" << s2 << endl;string s3(s2);cout << "s3=" << s3 << endl;string s4(10,'f');cout << "s4=" << s4 << endl;}
字符串赋值
void test90() {string str1;str1 = "hello world";cout << "str1=" << str1 << endl;string str2;str2 = str1;cout << "str2=" << str2 << endl;string str3;str3 = 'd';cout << "str3=" << str3 << endl;string str4;str4.assign("hello cpp");cout << "str4=" << str4 << endl;string str5;str5.assign("hello cpp", 5);cout << "str5=" << str5 << endl;string str6;str6.assign(str5);cout << "str6=" << str6 << endl;string str7;str7.assign(10,'w');cout << "str7=" << str7 << endl;}
字符串拼接
void test91() {string str = "hello";str += " world";cout << "str=" << str << endl;str += ';';cout << "str=" << str << endl;string str1 = "LOL DNF";str1 += str;cout << "str1=" << str1 << endl;string str2 = "I";str2.append("Love");cout << "str2=" << str2 << endl;str2.append("you and ...", 3);cout << "str2=" << str2 << endl;string st3 = "and money";str2.append(st3);cout << "str2=" << str2 << endl;string str4 = "you";str4.append(st3, 0,3);cout << "str4=" << str4 << endl;
}
查找
void test92() {string str1 = "abcdefg";int pos = str1.find("df");if (pos == -1){cout << "没有找到" << endl;} else {cout << "找到了pos=" << pos << endl;}pos = str1.rfind("de");cout << "找到了pos=" << pos << endl;str1.replace(1, 2, "12345");cout << str1 << endl;}
字符串比较
void test93() {string str1 = "hello";string str2 = "Xhello";if (str1.compare(str2) == 0) {cout << "str1 == str2" << endl;} else if (str1.compare(str2) > 0) {cout << "str1 > str2" << endl;} else {cout << "str1 < str2" << endl;}
}
字符存取
void test94() {string str1 = "hello";char c = str1[1];char d = str1.at(3);cout << c << d << endl;str1[3] = 'y';str1.at(1) = 'w';cout << str1 << endl;}
插入删除
void test95() {string str1 = "hello";cout << str1 << endl;str1.insert(5, " world;\0");cout << str1 << endl;str1.erase(11,1);cout << str1 << endl;}Hello, World!
end!
hello
hello world;
hello world
Program ended with exit code: 0
字串截取
void test96() {string str1 = "hello world;";string subStr = str1.substr(0,5);cout << subStr << endl;
}
demo
#include <iostream>
#include <string>
//1. 直接包含源文件
#include <vector>
#include <algorithm>
#include <deque>
using namespace std;
class Person20 {
public:Person20(string name,int score) {this->m_score = score;this->m_name = name;}string m_name;int m_score;
};
void createPerson(vector<Person20> &v) {string nameprefix = "abcde";for (int i = 0; i < 5; i++) {string name = "选手";name += nameprefix[i];int score = 0;Person20 p(name,score);v.push_back(p);}
}void setScore(vector<Person20> &v) {for (vector<Person20>::iterator it = v.begin(); it != v.end(); it++) {deque<int>d;for (int i = 0; i < 10; i++) {int score = rand() % 41 + 60;d.push_back(score);}sort(d.begin(), d.end());d.pop_back();d.pop_front();int sum = 0;for (deque<int>::iterator begin = d.begin(); begin != d.end(); begin++) {sum += (*begin);}int avg = sum / d.size();(*it).m_score = avg;}}void printPerson(vector<Person20> &v) {for (vector<Person20>::iterator it = v.begin(); it != v.end(); it++) {cout << "name = " << (*it).m_name << " score = " << (*it).m_score << endl;}cout << endl;}
void test110() {/// 随机数种子srand((unsigned int)time(NULL));vector<Person20> persons;createPerson(persons);printPerson(persons);setScore(persons);printPerson(persons);}
int main(int argc, const char * argv[]) {// insert code here...std::cout << "Hello, World!\n";std::cout << "end!\n";test110();return 0;
}
栈
#include <iostream>
#include <stack>
using namespace std;
void test111() {stack<int> s;s.push(1);s.push(2);s.push(3);s.push(4);cout << s.size()<< endl;while (!s.empty()) {cout << s.top() << endl;s.pop();}cout << s.size() << endl;}int main(int argc, const char * argv[]) {// insert code here...std::cout << "Hello, World!\n";std::cout << "end!\n";test111();return 0;
}
queue容器
#include <iostream>
#include <queue>
using namespace std;
class Person21 {
public:Person21(string name,int age) {this->m_age = age;this->m_name = name;}string m_name;int m_age;
};void test112() {queue<Person21> q;Person21 p("张三",22);q.push(p);Person21 p1("李四",24);q.push(p1);Person21 p2("王五",23);q.push(p2);Person21 p3("麻子",12);q.push(p3);cout << q.size()<< endl;while (!q.empty()) {cout << "front name = " << q.front().m_name << "age =" << q.front().m_age << endl;cout << "back name = " << q.back().m_name << "age =" << q.back().m_age << endl;q.pop();}cout << q.size() << endl;}int main(int argc, const char * argv[]) {// insert code here...std::cout << "Hello, World!\n";std::cout << "end!\n";test112();return 0;
}
List
list基本概念
功能:将数据进行链式存储
链表:(list)是一种物理存储单元上非连续的存储结构 数据元素的逻辑顺序是通过链表中的指针链连接实现的
链表组成:链表由一系列结点组成
结点 的组成:一个是存储数据元素的数据域 另一个是存储下一个结点地址的指针域
STL中的链表是一个双向循环链表
链表大存储方式并不是连续的内存空间 因此链表list中的迭代器只支持前移和后移属于双向链表。
List的优点
采用动态存储分配,不会造成内存浪费和溢出
链表执行插入和删除操作十分方便 修改指针即可 不需要移动大量元素
list缺点:
链表灵活但是空间(指针域)和时间(遍历)额外耗费较大
List由一个重要的性质 插入操作和删除操作不会造成原有list迭代器的失效 者在vector是不成立的;
List构造函数
list<T> list; //lis采用模版类实现对象的默认构造形式
list(beign,end) //构造函数将(begin,end)区间中的 元素拷贝给本身。
list(n,elem) //构造函数将n个elem拷贝给本身
list(const list &lst) //拷贝构造
#include <iostream>
#include <list>
using namespace std;
// 优点可以对任意位置进行快速插入或解除元素
// 缺点
//容器遍历速度没有数组快
//占用空间比数组大
void printList(const list<int> &lst) {for (list<int>::const_iterator begin = lst.begin(); begin != lst.end(); begin++) {cout << *begin << endl;}
}
void test113(){list<int> list1;list1.push_back(10);list1.push_back(30);list1.push_back(40);list1.push_back(50);printList(list1);list<int> lst2(list1.begin(),list1.end());printList(lst2);list<int> lst3(lst2);printList(lst3);list<int>lst4(10,8);printList(lst4);}
int main(int argc, const char * argv[]) {// insert code here...std::cout << "Hello, World!\n";std::cout << "end!\n";test113();return 0;
}
赋值和交换
void test114(){list<int> list1;list1.push_back(10);list1.push_back(30);list1.push_back(40);list1.push_back(50);printList(list1);list<int> list2;list2 = list1;printList(list2);list<int> list3;list3.assign(list2.begin(),list2.end());printList(list3);list<int> list4;list4.assign(10, 100);printList(list4);cout << "==========" << endl;list4.swap(list1);printList(list4);cout << "++++++++++++" << endl;printList(list1);}
list大小操作
void test115(){list<int> list1;list1.push_back(10);list1.push_back(30);list1.push_back(40);list1.push_back(50);printList(list1);cout << list1.size() << endl;cout << list1.empty() << endl;cout << "==========" << endl;list1.resize(10,100);printList(list1);cout << "++++++++++++" << endl;list1.resize(2);printList(list1);
}
list插入和删除
void test116(){list<int> list1;list1.push_back(10);list1.push_back(30);list1.push_back(40);list1.push_back(50);list1.push_front(111);list1.push_front(333);printList(list1);//尾删除list1.pop_back();printList(list1);cout << "==========" << endl;list1.pop_front();printList(list1);cout << "==========" << endl;list<int>::iterator begin = list1.begin();list1.insert(++begin, 201);printList(list1);cout << "==========" << endl;list<int>::iterator begin1 = list1.begin();list1.erase(++begin1);printList(list1);cout << "==========" << endl;list<int>::iterator begin2 = list1.begin();++begin2;list<int>::iterator begin3 = list1.begin();;++begin3;++begin3;list1.erase(begin2,begin3);printList(list1);cout << "==========" << endl;list1.push_back(100000);list1.push_back(100000);list1.push_back(100000);list1.remove(100000);printList(list1);cout << "==========" << endl;list1.clear();printList(list1);
}
数据存取
front() // 返回第一个元素
back()//返回最后一个元素
void test117(){list<int> list1;list1.push_back(10);list1.push_back(30);list1.push_back(40);list1.push_back(50);list1.push_front(111);list1.push_front(333);printList(list1);cout << "font" << list1.front() << endl;cout << "back" << list1.back() << endl;
}
list 不支持随机访问 例如迭代器随意+个数
反转排序
void test118(){list<int> list1;list1.push_front(111);list1.push_back(30);list1.push_back(40);list1.push_back(10);list1.push_back(50);list1.push_front(333);printList(list1);//反转cout << "==========" << endl;list1.reverse();printList(list1);cout << "==========" << endl;// 排序所有不支持随机访问的容器不能使用标准的算法list1.sort();// 默认从小到大printList(list1);list1.sort(myComPare);printList(list1);}
自定义排序规则
#include <iostream>
#include <string>
#include <list>
using namespace std;
class Person22 {
public:Person22(string name,int age, int height) {this->m_age = age;this->m_name = name;this->m_height = height;}string m_name;int m_age;int m_height;};
void printPersonInfo(const list<Person22> &lst) {for (list<Person22>:: const_iterator it = lst.begin(); it != lst.end(); it++) {cout << "名字:" << it->m_name << " 年龄:" << it->m_age << " 身高:" << it->m_height << endl;}
}
bool sortPersonList(Person22 &p1,Person22 &p2) {if (p1.m_age == p2.m_age) {return p1.m_height > p2.m_height;} else {return p1.m_age > p2.m_age;}
}
void test119(){list<Person22> list1;Person22 p1("张三",21,185);Person22 p2("李四",18,180);Person22 p3("王五",21,180);Person22 p4("麻子",22,182);Person22 p5("孙六",19,190);list1.push_back(p1);list1.push_back(p2);list1.push_back(p3);list1.push_back(p4);list1.push_back(p5);printPersonInfo(list1);cout << "==========" << endl;list1.sort(sortPersonList);printPersonInfo(list1);}
int main(int argc, const char * argv[]) {// insert code here...std::cout << "Hello, World!\n";std::cout << "end!\n";test119();return 0;
}
set
所有元素都会在插入时自动被排序
本质:
set/multiset 属于关联式容器 底层结构式用二叉树实现
set和multiset区别
set不允许容器中有重复的元素
multise允许容器中有重复的元素
set构造赋值
功能描述:创建set容器以及赋值
set(T) st;默认构造函数
set(const set &st) 拷贝构造函数
赋值
set& operator=(const. set&st) //重载等号操作符
#include <iostream>
#include <string>
#include <set>
using namespace std;
void printset(const set<int> &s) {for (set<int>::const_iterator begin = s.begin();begin != s.end(); begin++) {cout << *begin << endl;}
}
void test120() {//set 插入后会继续排序 set容器中不会有重复元素set<int> s1;s1.insert(10);s1.insert(40);s1.insert(20);s1.insert(30);s1.insert(30);printset(s1);set<int> s2(s1);printset(s2);set<int> s3;s3 = s1;printset(s3);}int main(int argc, const char * argv[]) {// insert code here...std::cout << "Hello, World!\n";std::cout << "end!\n";test120();return 0;
}
set大小和交换
void test121() {//set 插入后会继续排序 set容器中不会有重复元素set<int> s1;s1.insert(10);s1.insert(40);s1.insert(20);s1.insert(30);s1.insert(30);printset(s1);cout << "======"<< endl;cout << s1.size()<< endl;cout << "======"<< endl;cout << s1.empty()<< endl;set<int> s2;s2.insert(1);s2.insert(4);s2.insert(7);cout << "======"<< endl;s1.swap(s2);printset(s1);cout << "======"<< endl;printset(s2);}
插入和删除
void test122() {set<int> s1;s1.insert(10);s1.insert(40);s1.insert(20);s1.insert(30);s1.insert(30);printset(s1);cout << "======"<< endl;s1.erase(s1.begin());printset(s1);cout << "======"<< endl;s1.erase(30);printset(s1);cout << "======"<< endl;s1.erase(s1.begin(), s1.end());printset(s1);s1.clear();}
查询和统计
void test123() {set<int> s1;s1.insert(10);s1.insert(40);s1.insert(20);s1.insert(30);s1.insert(30);printset(s1);set<int>::iterator pos = s1.find(10);set<int>::iterator pos1 = s1.find(50);cout << *pos << endl;if (pos != s1.end()) {cout << "10find"<< endl;} else {cout << "10nofind"<< endl;}cout << "======"<< endl;cout << *pos1 << endl;if (pos1 != s1.end()) {cout << "50find"<< endl;} else {cout << "50nofind"<< endl;}cout << "======"<< endl;cout << s1.count(40) << endl;
}
multiset
void test124() {set<int> s1;pair<set<int>::iterator, bool> ret = s1.insert(10);if (ret.second) {cout << "插入成功" << endl;} else {cout << "插入失败" << endl;}ret = s1.insert(10);if (ret.second) {cout << "插入成功" << endl;} else {cout << "插入失败" << endl;}multiset<int>ms;ms.insert(10);ms.insert(10);ms.insert(10);ms.insert(10);ms.insert(10);cout << ms.count(10) << endl;
}
对组pair
void test125() {pair<string, int>p("tom",20);cout << p.first << p.second << endl;pair<string, int>p2 = make_pair("team", 20);cout << p2.first << p2.second << endl;}
set排序
class MyCompare{
public:bool operator()(int v1,int v2) {return v1 > v2;}
};void test126() {set<int> s1;s1.insert(10);s1.insert(40);s1.insert(20);s1.insert(30);s1.insert(30);printset(s1);cout << "======"<< endl;set<int,MyCompare> s2;s2.insert(12);s2.insert(10);s2.insert(1);s2.insert(3);s2.insert(4);for (set<int,MyCompare>::iterator it = s2.begin(); it != s2.end(); it++) {cout << *it << endl;}}
自定义类型 一定要在自定义类型内写排序规则
#include <iostream>
#include <set>class Person23 {
public:Person23(string name,int age) {this->m_age = age;this->m_name = name;}string m_name;int m_age;
};
class comparePearson{
public:bool operator()(const Person23 &p1,const Person23 &p2) {return p1.m_age > p2.m_age;}
};
void test127() {set<Person23,comparePearson>s1;Person23 p1("张三",21);Person23 p2("李四",18);Person23 p3("王五",21);Person23 p4("麻子",22);Person23 p5("孙六",19);s1.insert(p1);s1.insert(p2);s1.insert(p3);s1.insert(p4);s1.insert(p5);for (set<Person23>::iterator it = s1.begin(); it != s1.end(); it++) {cout << "name = " << it->m_name << " age= " << it->m_age << endl;}
}
int main(int argc, const char * argv[]) {// insert code here...std::cout << "Hello, World!\n";std::cout << "end!\n";test127();return 0;
}
map
map中所有元素都是pair
pair中第一个元素为key起到索引等作用 第二个元素为value
所有元素都会根据元素的键值自动排序
本质
map/multimap属于关联式容器 底层结构是用二叉树实现
优点
可以根据key值快速找到value值
map和multimap区别
map不允许容器中有重复key值元素
multimap允许容器中有重复key值元素
构造函数
#include <iostream>
#include <map>
using namespace std;
void printmap(map<int, int> &m) {for (map<int,int>::iterator it = m.begin(); it != m.end(); it++) {cout << "key=" << (*it).first << " value = " << (*it).second << endl;}
}
void test128(){map<int, int> m;// 会按key排序m.insert(pair<int, int>(1,10));m.insert(pair<int, int>(3,13));m.insert(pair<int, int>(2,12));printmap(m);map<int, int> m2(m);printmap(m2);map<int, int> m3;m3 = m2;printmap(m3);
}int main(int argc, const char * argv[]) {// insert code here...std::cout << "Hello, World!\n";std::cout << "end!\n";test128();return 0;
}
大小和交换
void test129(){map<int, int> m;// 会按key排序m.insert(pair<int, int>(1,10));m.insert(pair<int, int>(3,13));m.insert(pair<int, int>(2,12));printmap(m);cout << "======" << endl;cout << m.size() << endl;cout << "======" << endl;map<int, int> m2;m2.insert(pair<int, int>(22,10));m2.insert(pair<int, int>(33,13));m2.insert(pair<int, int>(44,12));m.swap(m2);cout << "======" << endl;printmap(m);cout << "======" << endl;printmap(m2);
}
int main(int argc, const char * argv[]) {// insert code here...std::cout << "Hello, World!\n";std::cout << "end!\n";test129();return 0;
}
插入删除
void test130(){map<int, int> m;// 会按key排序m.insert(pair<int, int>(1,10));m.insert(pair<int, int>(3,13));m.insert(pair<int, int>(2,12));//插入到第二种方式m.insert(make_pair(4, 12));//插入的第三种方式m.insert(map<int,int>::value_type(5,18));//第四种方式m[6] = 20;printmap(m);cout << "======" << endl;map<int, int>::iterator it = m.begin();m.erase(it);printmap(m);cout << "======" << endl;// 按key删除m.erase(3);printmap(m);cout << "======" << endl;m.erase(m.begin(), m.end());printmap(m);cout << "======" << endl;m.clear();printmap(m);
}
查找和统计
void test131(){map<int, int> m;// 会按key排序m.insert(pair<int, int>(1,10));m.insert(pair<int, int>(3,13));m.insert(pair<int, int>(2,12));printmap(m);map<int,int>::iterator pos;// 是通过key查找的pos = m.find(1);if (pos != m.end()) {cout << "1find"<< endl;} else {cout << "1nofind"<< endl;}cout << "======"<< endl;pos = m.find(5);if (pos != m.end()) {cout << "5find"<< endl;} else {cout << "5nofind"<< endl;}cout << "======"<< endl;// 找到是1 没找到为0 multimap 找到结果可能大于一cout << m.count(1) << endl;cout << m.count(10) << endl;}
排序
这个仿函数里面的const必须加上 我在xcode中没加 编译不过 其他平台没试
class Cmp{
public:bool operator () (int v1,int v2) const {return v1 > v2;}
};void test132(){map<int,int,Cmp> m;// 会按key排序m.insert(pair<int, int>(1,10));m.insert(pair<int, int>(3,13));m.insert(pair<int, int>(2,12));for (map<int, int,Cmp>::iterator it = m.begin(); it != m.end(); it++) {cout << " key = " << it->first << " value = " << it->second << endl;}
}int main(int argc, const char * argv[]) {// insert code here...std::cout << "Hello, World!\n";std::cout << "end!\n";test132();return 0;
}
class Worker{
public:
// Worker(string name ,int salary) {
// this->m_name = name;
// this->m_salary = salary;
// }string m_name;int m_salary;
};
void creatework(vector<Worker> &v) {string nameseed = "ABCDEFGHIJ";for (int i = 0; i < 10; i++) {Worker w;w.m_name = "员工";w.m_name += nameseed[i];w.m_salary = rand() % 10001 + 30000;v.push_back(w);}
}void setGroup(vector<Worker> &v,multimap<int, Worker>&m) {for(vector<Worker>::iterator it = v.begin(); it != v.end();it++) {int depId = rand() % 3;m.insert(make_pair(depId, *it));cout << "setGroup" << "name = " << it->m_name << " salary = " << it->m_salary << endl;}
}
void showdepWorkInfo(int dep, multimap<int, Worker>::iterator it, multimap<int, Worker>&m) {int index = 0;int count = int(m.count(dep));for(;it != m.end() && index < count; it++, index++){cout << "showdepWorkInfo" << "name = " << it->second.m_name << " salary = " << it->second.m_salary << endl;}
}void showWorkByGroup(multimap<int, Worker>&m) {cout << "部门1" << endl;multimap<int, Worker>::iterator it = m.find(0);;
// int index = 0;
// int count = int(m.count(0));
// for(;it != m.end() && index < count; it++, index++){
// cout << "setGroup" << "name = " << it->second.m_name << " salary = " << it->second.m_salary << endl;
// }showdepWorkInfo(0,it,m);cout << "部门2" << endl;it = m.find(1);showdepWorkInfo(1,it,m);cout << "部门3" << endl;it = m.find(2);showdepWorkInfo(2,it,m);}void test133() {srand((unsigned int)time(NULL));vector<Worker> works;creatework(works);for(vector<Worker>::iterator it = works.begin(); it != works.end();it++) {cout << "name = " << it->m_name << " salary = " << it->m_salary << endl;}//multimap<int, Worker> wmap;setGroup(works,wmap);showWorkByGroup(wmap);
}
int main(int argc, const char * argv[]) {// insert code here...std::cout << "Hello, World!\n";std::cout << "end!\n";test133();return 0;
}
函数对象
概念
重载函数调用操作符的类 其对象称为函数对象
函数对象使用重载()时 行为类似函数调用 也叫仿函数
本质
函数对象(仿函数)就是一个类 不是一个函数
函数对象特点
函数对象在使用时可以像普通函数那样调用,可以有参数可以有返回值
函数对象超出普通函数的概念 函数对象可以有自己的状态
函数对象也可以作为参数传递
#include <iostream>
#include <string>
using namespace std;
class MyAdd {
public:int operator() (int a,int b) {return a + b;}
};
class MyPrint {
public://保存值维持状态int num;void operator() (string test) {cout << test << endl;num += 1;}
};
/// 当成参数传递
void doPrint(MyPrint &p, string ts) {p(ts);
}
void test134(){MyAdd m;cout << m(20,30) << endl;MyPrint p;p.num = 0;p("1");p("1");p("1");p("1");cout << p.num << endl;doPrint(p, "iooooooooo");
}int main(int argc, const char * argv[]) {// insert code here...std::cout << "Hello, World!\n";std::cout << "end!\n";test134();return 0;
}
谓词
返回bool类型的仿函数称为谓词
如果 operator() 接收一个参数 那么叫一元谓词
如果operator() 接收两个参数 叫二元谓词
// 一元谓词
class GrightFive {public:bool operator() (int a) {return a > 5;}
};
void test135(){vector<int> v;for(int i = 0;i < 10;i++) {v.push_back(i);}vector<int>:: iterator it = find_if(v.begin(), v.end(),GrightFive());if (it == v.end()) {cout << "没有找到" << endl;} else {cout << "找到了" << endl;}
}
二元
class intSort {
public:bool operator() (int a, int b) {return a > b;}
};
void test136(){vector<int> v;v.push_back(100);v.push_back(130);v.push_back(80);v.push_back(70);sort(v.begin(), v.end(), intSort());for(vector<int>::iterator it = v.begin(); it != v.end();it++){cout << *it << endl;}
}
内建函数对象
算数仿函数
void test137(){negate<int> n;//取反cout << n(50) <<endl;plus<int> p;cout << p(20,30) <<endl;}
关系仿函数
void test138(){vector<int> v;v.push_back(100);v.push_back(130);v.push_back(80);v.push_back(70);sort(v.begin(), v.end(), greater<int>());for(vector<int>::iterator it = v.begin(); it != v.end();it++){cout << *it << endl;}}
逻辑仿函数
void test139(){vector<bool> v;v.push_back(true);v.push_back(false);v.push_back(true);v.push_back(false);for(vector<bool>::iterator it = v.begin(); it != v.end();it++){cout << *it << endl;}vector<bool> v2;v2.resize(v.size());transform(v.begin(), v.end(), v2.begin(), logical_not<bool>());for(vector<bool>::iterator it = v2.begin(); it != v2.end();it++){cout << *it << endl;}}
stl常用算法
#include <algorithm>必须导入
foreach
void printIntValue(int &val) {cout << val <<endl;cout <<endl;}
class printInt {
public:void operator() (int val) {cout << val <<endl;}};void test140(){vector<int> v;v.push_back(100);v.push_back(130);v.push_back(80);v.push_back(70);sort(v.begin(), v.end(), greater<int>());
// for(vector<int>::iterator it = v.begin(); it != v.end();it++){
// cout << *it << endl;
// }for_each(v.begin(), v.end(), printIntValue);cout << "=============" <<endl;for_each(v.begin(), v.end(), printInt());}
transform
void test141(){vector<int> v;v.push_back(100);v.push_back(130);v.push_back(80);v.push_back(70);vector<int> v2;//目标容器必修提前开辟空间不然必crashv2.resize(v.size());transform(v.begin(), v.end(), v2.begin(), Transform());for(vector<int>::iterator it = v2.begin(); it != v2.end();it++){cout << *it << endl;}}