C++ STL

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;}}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/673527.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【Git版本控制 04】标签管理

目录 一、创建标签 二、查看标签 三、推送标签 四、删除标签 一、创建标签 标签tag&#xff0c;是对某次 commit 的⼀个标识&#xff0c;相当于起了⼀个别名。 相较于难以记住的 commit id &#xff0c; tag 很好的解决这个问题&#xff0c;因为 tag ⼀定要给⼀个让⼈容易…

使用ChatGpt和文心一言辅助文章创作

近期在写数字水浒系列文章&#xff0c;使用了ChatGpt和文心一言进行辅助创作&#xff0c;整体感受不错&#xff0c;提高了工作效率。 在使用过程中&#xff0c;感觉文心的中文能力更强一些&#xff0c;主要体现在&#xff1a; 1 语料库更大&#xff0c;比如对水浒传了解的更多…

Text2SQL研究-Chat2DB体验与剖析

文章目录 概要业务数据库配置Chat2DB安装设置原理剖析 小结 概要 近期笔者在做Text2SQL的研究&#xff0c;于是调研了下Chat2DB&#xff0c;基于车辆订单业务做了一些SQL生成验证&#xff0c;有了一点心得&#xff0c;和大家分享一下.&#xff1a; 业务数据库设置 基于车辆订…

Linux第43步_移植ST公司uboot的第4步_uboot测试

uboot移植结束后&#xff0c;需要进行测试。 1、烧录程序 1)、将STM32MP157开发板的网络接口与路由器的网络接口通过网线连接起来。 2)、将开发板的串口和电脑通过USB线连接起来。 3)、将开发板的USB OTG接口和电脑通过USB线连接起来。 4)、将开发板上拨码开关拨到“000”…

鸿蒙(HarmonyOS)项目方舟框架(ArkUI)之ScrollBar组件

鸿蒙&#xff08;HarmonyOS&#xff09;项目方舟框架&#xff08;ArkUI&#xff09;之ScrollBar组件 一、操作环境 操作系统: Windows 10 专业版、IDE:DevEco Studio 3.1、SDK:HarmonyOS 3.1 二、ScrollBar组件 鸿蒙&#xff08;HarmonyOS&#xff09;滚动条组件ScrollBar&…

Leetcode3020. 子集中元素的最大数量

Every day a Leetcode 题目来源&#xff1a;3020. 子集中元素的最大数量 解法1&#xff1a;哈希 枚举 用一个哈希表统计数组 nums 中的元素及其出现次数。 暴力枚举数组中的数&#xff0c;作为 x&#xff0c;然后不断看 x2,x4,⋯ 在数组中的个数。直到个数不足 2 个为止&a…

搭建macOS开发环境-1:准备工作

请记住&#xff1a; 最重要的准备工作永远是&#xff1a;备份数据 !!! 通过图形界面检查 Mac 的 CPU 类型&#xff1a; 在搭载 Apple 芯片的 Mac 电脑上&#xff0c;“关于本机”会显示一个标有“芯片”的项目并跟有相应芯片的名称&#xff1a; 通过命令行检查Mac的CPU类型 …

使用vite创建vue+ts项目,整合常用插件(scss、vue-router、pinia、axios等)和配置

一、检查node版本 指令&#xff1a;node -v 为什么要检查node版本&#xff1f; Vite 需要 Node.js 版本 18&#xff0c;20。然而&#xff0c;有些模板需要依赖更高的 Node 版本才能正常运行&#xff0c;当你的包管理器发出警告时&#xff0c;请注意升级你的 Node 版本。 二、创…

七、Nacos源码系列:Nacos服务发现

目录 一、服务发现 二、getServices()&#xff1a;获取服务列表 2.1、获取服务列表 2.2、总结图 三、getInstances(serviceId)&#xff1a;获取服务实例列表 3.1、从缓存中获取服务信息 3.2、缓存为空&#xff0c;执行订阅服务 3.2.1、调度更新&#xff0c;往线程池中…

【Spring】Tomcat服务器部署

&#x1f4dd;个人主页&#xff1a;五敷有你 &#x1f525;系列专栏&#xff1a;Spring⛺️稳中求进&#xff0c;晒太阳 单体项目部署 本地工作 项目在本地开发完毕之后进行一些必要参数的修改。 比如&#xff1a; 数据库的JDBC的配置文件&#xff0c;还有前端页面的…

项目02《游戏-06-开发》Unity3D

基于 项目02《游戏-05-开发》Unity3D &#xff0c; 接下来做 背包系统的 存储框架 &#xff0c; 首先了解静态数据 与 动态数据&#xff0c;静态代表不变的数据&#xff0c;比如下图武器Icon&#xff0c; 其中&#xff0c;武器的名称&#xff0c;描述&#xff…

Swift Combine 发布者publisher的生命周期 从入门到精通四

Combine 系列 Swift Combine 从入门到精通一Swift Combine 发布者订阅者操作者 从入门到精通二Swift Combine 管道 从入门到精通三 1. 发布者和订阅者的生命周期 订阅者和发布者以明确定义的顺序进行通信&#xff0c;因此使得它们具有从开始到结束的生命周期&#xff1a; …

课时17:本地变量_命令变量

2.2.3 命令变量 学习目标 这一节&#xff0c;我们从 基础知识、简单实践、小结 三个方面来学习。 基础知识 基本格式 定义方式一&#xff1a;变量名命令注意&#xff1a; 是反引号定义方式二&#xff1a;变量名$(命令)执行流程&#xff1a;1、执行 或者 $() 范围内的命令…

pycharm像jupyter一样在控制台查看后台变量

更新下&#xff1a;这个一劳永逸不用一个一个改 https://blog.csdn.net/Onlyone_1314/article/details/109347481 右上角运行

Spring IoC容器(四)容器、环境配置及附加功能

本文内容包括容器的Bean 及 Configuration 注解的使用、容器环境的配置文件及容器的附加功能&#xff08;包括国际化消息、事件发布与监听&#xff09;。 1 容器配置 在注解模式下&#xff0c;Configuration 是容器核心的注解之一&#xff0c;可以在其注解的类中通过Bean作用…

DevOps落地笔记-20|软件质量:决定系统成功的关键

上一课时介绍通过提高工程效率来提高价值交付效率&#xff0c;从而提高企业对市场的响应速度。在提高响应速度的同时&#xff0c;也不能降低软件的质量&#xff0c;这就是所谓的“保质保量”。具备高质量软件&#xff0c;高效率的企业走得更快更远。相反&#xff0c;低劣的软件…

消息中间件之RocketMQ源码分析(八)

RocketMQ中的消息过滤 RocketMQ设计了消息过滤&#xff0c;来解决大量无意义流量的传输:即对于客户端不需要的消息&#xff0c; Broker就不会传输给客户端&#xff0c;以免浪费宽带&#xff0c;RocketMQ4.2.0支持Tag过滤、SQL92过滤、Filter Server过滤 Tag过滤 第一步:用户发…

蓝桥杯Web应用开发-CSS3 新特性【练习三:文本阴影】

文本阴影 text-shadow 属性 给文本内容添加阴影的效果。 文本阴影的语法格式如下&#xff1a; text-shadow: x-offset y-offset blur color;• x-offset 是沿 x 轴方向的偏移距离&#xff0c;允许负值&#xff0c;必须参数。 • y-offset 是沿 y 轴方向的偏移距离&#xff0c…

Swift Combine 管道 从入门到精通三

Combine 系列 Swift Combine 从入门到精通一Swift Combine 发布者订阅者操作者 从入门到精通二 1. 用弹珠图描述管道 函数响应式编程的管道可能难以理解。 发布者生成和发送数据&#xff0c;操作符对该数据做出响应并有可能更改它&#xff0c;订阅者请求并接收这些数据。 这…

LoveWall v2.0Pro社区型校园表白墙源码

校园表白墙&#xff0c;一个接近于社区类型的表白墙&#xff0c;LoveWall。 源码特色&#xff1b; 点赞&#xff0c; 发评论&#xff0c; 发弹幕&#xff0c; 多校区&#xff0c; 分享页&#xff0c; 涉及违禁物等名词进行检测&#xff01; 安装教程: 环境要求&#xff1b;…