3.1.8 string插入和删除
功能描述:对string字符串进行插入和删除字符操作
函数原型:
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个字符
#include<iostream> using namespace std; #include<iostream> //string 插入和删除 void test01() { string str = "hello"; //插入 str.insert(1, "222"); cout << "str = " << str << endl; //删除 str.erase(1, 3); //从索引1开始删除3个 cout << "str = " << str << endl; } int main() { test01(); system("pause"); return 0; }
str = h222ello str = hello 请按任意键继续. . .
3.1.9 string子串
功能描述:从字符串中获取想要的子串
函数原型:string substr(int pos = 0, int n = npos) const;
//返回由pos开始的n个字符组成的字符串
#include<iostream> using namespace std; #include<iostream> //string子串 void test01() { string str = "abcdef"; string subStr = str.substr(1, 3); //从索引1开始截3个 cout << "sunStr = " << subStr << endl; } //实用操作 void test02() { string email = "zhangsan@sina.com"; int pos = email.find("@"); string usrName = email.substr(0, pos); cout << "usrName = " << usrName << endl; } int main() { test01(); test02(); system("pause"); return 0; }
sunStr = bcd usrName = zhangsan 请按任意键继续. . .
3.2 vector容器
3.2.1 vector基本概念
功能:vector数据结构和数组非常相似,也称为单端数组
vector与普通数组区别:不同之处在于数组是静态空间,而vector可以动态扩展
动态扩展:并不是在原空间之后续接新空间,而是找更大的内存空间,然后将原数据拷贝新空间,释放原空间
vector容器的迭代器是支持随机访问的迭代器
3.2.2 vector构造函数
功能描述:创建vector容器
函数原型:
vector<T> v;
//采用模板实现类实现,默认构造函数
vector(v.begin(), v.end());
//将v[begin(), end())区间中的元素拷贝给本身。
vector(n, elem);
//构造函数将n个elem拷贝给本身。
vector(const vector &vec);
//拷贝构造函数。
#include<iostream> using namespace std; #include<vector> void printVector(vector<int>&v){ for (vector<int>::iterator it = v.begin(); it != v.end(); it++) { cout << *it << " "; } cout << endl; } //vector容器构造 void test01() { vector<int>v1; //默认构造 无参构造 for (int i = 0; i < 10; i++) { v1.push_back(i); } printVector(v1); //通过区间方式进行构造 vector<int>v2(v1.begin(), v1.end()); printVector(v2); //n个elem方式构造 vector<int>v3(10, 100); //10个100 printVector(v3); //拷贝构造 vector<int>v4(v3); printVector(v4); } int main() { test01(); system("pause"); return 0; }
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 请按任意键继续. . .
3.2.3 vector赋值操作
功能描述:给vector容器进行赋值
函数原型:
vector& operator=(const vector &vec);
//重载等号操作符
assign(beg, end);
//将[beg, end)区间中的数据拷贝赋值给本身。
assign(n, elem);
//将n个elem拷贝赋值给本身
#include<iostream> using namespace std; #include<vector> void printVector(vector<int>& v) { for (vector<int>::iterator it = v.begin(); it != v.end(); it++) { cout << *it << " "; } cout << endl; } //vector赋值 void test01() { vector<int>v1; for (int i = 0; i < 10; i++) { v1.push_back(i); } printVector(v1); //赋值 = vector<int>v2; v2 = v1; printVector(v2); //assign vector<int>v3; v3.assign(v1.begin(), v1.end()); printVector(v3); //n个elem方式赋值 vector<int>v4; v4.assign(10, 100); //10个100 printVector(v4); } int main() { test01(); system("pause"); return 0; }
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 100 100 100 100 100 100 100 100 100 100 请按任意键继续. . .
3.2.4 vector容量和大小
功能描述:对vector容器的容量和大小操作
函数原型:
empty();
//判断容器是否为空
capacity();
//容器的容量
size();
//返回容器中元素的个数
resize(int num);
//重新指定容器的长度为num,若容器变长,则以默认值填充新位置。
//如果容器变短,则末尾超出容器长度的元素被删除。
resize(int num, elem);
//重新指定容器的长度为num,若容器变长,则以elem值填充新位置。
//如果容器变短,则末尾超出容器长度的元素被删除
#include<iostream> using namespace std; #include<vector> //vector容器的容量和大小操作 void printVector(vector<int>& v) { for (vector<int>::iterator it = v.begin(); it != v.end(); it++) { cout << *it << " "; } cout << endl; } void test01() { vector<int> v1; for (int i = 0; i < 10; i++) { v1.push_back(i); } printVector(v1); if (v1.empty()) //为真 则为空 { cout << "v1为空" << endl; } else { cout << "v1不为空" << endl; cout << "v1的容量为: " << v1.capacity() << endl; cout << "v1的大小为: " << v1.size() << endl; } //重新指定大小 v1.resize(15, 100); //默认填充为最后那个参数 cout << "\n重新指定大小后:" << endl; printVector(v1); cout << "现在v1的容量为: " << v1.capacity() << endl; cout << "现在v1的大小为: " << v1.size() << endl; //重新指定的大小过小 则删除超出部分 cout << "\n重新指定的大小过小 则删除超出部分. . . " << endl; v1.resize(5); printVector(v1); } int main() { test01(); system("pause"); return 0; }
0 1 2 3 4 5 6 7 8 9 v1不为空 v1的容量为: 13 v1的大小为: 10 重新指定大小后: 0 1 2 3 4 5 6 7 8 9 100 100 100 100 100 现在v1的容量为: 19 现在v1的大小为: 15 重新指定的大小过小 则删除超出部分. . . 0 1 2 3 4 请按任意键继续. . .
3.2.5 vector插入和删除
功能描述:对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();
//删除容器中所有元素
#include<iostream> using namespace std; #include<vector> //vector插入和删除 void printVector(vector<int>& v) { for (vector<int>::iterator it = v.begin(); it != v.end(); it++) { cout << *it << " "; } cout << endl; } void test01() { vector<int> v1; //尾插 v1.push_back(10); v1.push_back(20); v1.push_back(30); v1.push_back(40); v1.push_back(50); //遍历 printVector(v1); //尾删 v1.pop_back(); printVector(v1); //插入 v1.insert(v1.begin(), 100); //第一个参数是迭代器 printVector(v1); v1.insert(v1.begin(), 2, 200); //两个200 printVector(v1); //删除 参数也是迭代器 v1.erase(v1.begin()); printVector(v1); v1.erase(v1.begin(), v1.end()); //提供一个删除的区间 printVector(v1); } int main() { test01(); system("pause"); return 0; }
10 20 30 40 50 10 20 30 40 100 10 20 30 40 200 200 100 10 20 30 40 200 100 10 20 30 40 请按任意键继续. . .
3.2.6 vector数据存取
功能描述:对vector中的数据的存取操作
函数原型:
at(int idx);
//返回索引idx所指的数据
operator[];
//返回索引idx所指的数据
front();
//返回容器中第一个数据元素
back();
//返回容器中最后一个数据元素
#include<iostream> using namespace std; #include<vector> //vector容器 数据存取 void test01() { vector<int>v1; for (int i = 0; i < 10; i++) { v1.push_back(i); } //利用[]访问数组中元素 for (int i = 0; i < v1.size(); i++) { cout << v1[i] << " "; } cout << endl; //利用at方式访问元素 for (int i = 0; i < v1.size(); i++) { cout << v1.at(i) << " "; } cout << endl; //获取第一个元素 cout << "第一个元素为:" << v1.front() << endl; //获取最后一个元素 cout << "最后一个元素为:" << v1.back() << endl; } int main() { test01(); system("pause"); return 0; }
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 第一个元素为:0 最后一个元素为:9 请按任意键继续. . .
3.2.7 vector互换容器
功能描述:实现两个容器内元素进行互换
函数原型:swap(vec);
// 将vec与本身的元素互换
#include<iostream> using namespace std; #include<vector> //vector容器 互换 //1、基本的使用 void printVector(vector<int>& v) { for (vector<int>::iterator it = v.begin(); it != v.end(); it++) { cout << *it << " "; } cout << endl; } void test01() { vector<int>v1; for (int i = 0; i < 10; i++) { v1.push_back(i); } cout << "交换前:" << endl; printVector(v1); vector<int> v2; for (int i = 10; i > 0; i--) { v2.push_back(i); } printVector(v2); cout << "交换后:" << endl; v1.swap(v2); printVector(v1); printVector(v2); } //2、实际用途 //巧用swap可以收缩内存空间 void test02() { vector<int> v; for (int i = 0; i < 100000; i++) { v.push_back(i); } cout << "v的容量为:" << v.capacity() << endl; cout << "v的大小为:" << v.size() << endl; v.resize(3); cout << "v的容量为:" << v.capacity() << endl; cout << "v的大小为:" << v.size() << endl; cout << "\n"; //巧用swap收缩内存 vector<int>(v).swap(v); cout << "v的容量为:" << v.capacity() << endl; cout << "v的大小为:" << v.size() << endl; } int main() { test01(); test02(); system("pause"); return 0; }
交换前: 0 1 2 3 4 5 6 7 8 9 10 9 8 7 6 5 4 3 2 1 交换后: 10 9 8 7 6 5 4 3 2 1 0 1 2 3 4 5 6 7 8 9 v的容量为:138255 v的大小为:100000 v的容量为:138255 v的大小为:3 v的容量为:3 v的大小为:3 请按任意键继续. . .
3.2.8 vector预留空间
功能描述:减少vector在动态扩展容量时的扩展次数
函数原型:reserve(int len);
//容器预留len个元素长度,预留位置不初始化,元素不可访问。
#include<iostream> using namespace std; #include<vector> //vector 预留空间 void printVector(vector<int>& v) { for (vector<int>::iterator it = v.begin(); it != v.end(); it++) { cout << *it << " "; } cout << endl; } void test01() { vector<int>v; //利用reverse预留空间 v.reserve(100000); int num = 0; //统计开辟次数 int* p = NULL; for (int i = 0; i < 100000; i++) { v.push_back(i); if (p != &v[0]) { p = &v[0]; num++; } } cout << "num = " << num << endl; //没用预留空间时是30次 } int main() { test01(); system("pause"); return 0; }
num = 1 请按任意键继续. . .
总结:如果数据量较大,可以一开始利用reserve预留空间
3.3 deque容器
3.3.1 deque容器基本概念
功能:双端数组,可以对头端进行插入删除操作
deque与vector区别:
- vector对于头部的插入删除效率低,数据量越大,效率越低
- deque相对而言,对头部的插入删除速度回比vector快
- vector访问元素时的速度会比deque快,这和两者内部实现有关
deque内部工作原理:
deque内部有个中控器,维护每段缓冲区中的内容,缓冲区中存放真实数据
中控器维护的是每个缓冲区的地址,使得使用deque时像一片连续的内存空间
deque容器的迭代器也是支持随机访问的
3.3.2 deque构造函数
功能描述:deque容器构造
函数原型:
deque<T> deqT;
//默认构造形式
deque(beg, end);
//构造函数将[beg, end)区间中的元素拷贝给本身。
deque(n, elem);
//构造函数将n个elem拷贝给本身。
deque(const deque &deq);
//拷贝构造函数
#include<iostream> using namespace std; #include<deque> //deque 构造函数 void printDeque(const deque<int>&d) { //const只读 for (deque<int>::const_iterator it = d.begin(); it != d.end(); it++) { //*it = 100; 现在容器中数据不可以修改了 cout << *it << " "; } cout << endl; } void test01() { deque<int> d1; for (int i = 0; i < 10; i++) { d1.push_back(i); } printDeque(d1); //2.区间方式赋值 deque<int> d2(d1.begin(), d1.end()); printDeque(d2); //3. deque<int>d3(10, 100); //10个100 printDeque(d3); //4.拷贝构造赋值 deque<int>d4(d3); printDeque(d4); } int main() { test01(); system("pause"); return 0; }
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 请按任意键继续. . .
总结:deque容器和vector容器的构造方式几乎一致,灵活使用即可
3.3.3 deque赋值操作
功能描述:给deque容器进行赋值
函数原型:
deque& operator=(const deque &deq);
//重载等号操作符
assign(beg, end);
//将[beg, end)区间中的数据拷贝赋值给本身。
assign(n, elem);
//将n个elem拷贝赋值给本身。
#include<iostream> using namespace std; #include<deque> //deque容器 赋值操作 void printDeque(const deque<int>&d) { //const只读 for (deque<int>::const_iterator it = d.begin(); it != d.end(); it++) { //*it = 100; 现在容器中数据不可以修改了 cout << *it << " "; } cout << endl; } void test01() { deque<int> d1; for (int i = 0; i < 10; i++) { d1.push_back(i); } printDeque(d1); //operator=赋值 deque<int>d2; d2 = d1; printDeque(d2); //assign赋值 deque<int>d3; d3.assign(d1.begin(), d1.end()); printDeque(d3); //第4种 deque<int>d4; d4.assign(10, 100); printDeque(d4); } int main() { test01(); system("pause"); return 0; }
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 100 100 100 100 100 100 100 100 100 100 请按任意键继续. . .
3.3.4 deque大小操作
功能描述:对deque容器的大小进行操作
函数原型:
deque.empty();
//判断容器是否为空
deque.size();
//返回容器中元素的个数
deque.resize(num);
//重新指定容器的长度为num,若容器变长,则以默认值填充新位置
//如果容器变短,则末尾超出容器长度的元素被删除。
deque.resize(num, elem);
//重新指定容器的长度为num,若容器变长,则以elem值填充新位置。
//如果容器变短,则末尾超出容器长度的元素被删除。
#include<iostream> using namespace std; #include<deque> //deque容器 赋值操作 void printDeque(const deque<int>&d) { //const只读 for (deque<int>::const_iterator it = d.begin(); it != d.end(); it++) { //*it = 100; 现在容器中数据不可以修改了 cout << *it << " "; } cout << endl; } void test01() { deque<int> d1; for (int i = 0; i < 10; i++) { d1.push_back(i); } printDeque(d1); if (d1.empty()) { cout << "d1为空" << endl; } else { cout << "d1不为空" << endl; cout << "d1的大小为:" << d1.size() << endl; } //重新指定大小 d1.resize(15,111); //111填充到15个 printDeque(d1); d1.resize(5); printDeque(d1); } int main() { test01(); system("pause"); return 0; }
0 1 2 3 4 5 6 7 8 9 d1不为空 d1的大小为:10 0 1 2 3 4 5 6 7 8 9 111 111 111 111 111 0 1 2 3 4 请按任意键继续. . .
3.3.5 deque 插入和删除
功能描述:向deque容器中插入和删除数据
函数原型:
两端插入操作:
push_back(elem);
//在容器尾部添加一个数据
push_front(elem);
//在容器头部插入一个数据
pop_back();
//删除容器最后一个数据
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位置的数据,返回下一个数据的位置。
#include<iostream> using namespace std; #include<deque> //deque容器 插入和删除 void printDeque(const deque<int>&d) { //const只读 for (deque<int>::const_iterator it = d.begin(); it != d.end(); it++) { //*it = 100; 现在容器中数据不可以修改了 cout << *it << " "; } cout << endl; } void test01() { deque<int> d1; //尾插 d1.push_back(10); d1.push_back(20); //头插 d1.push_front(100); d1.push_front(200); printDeque(d1); //尾删 d1.pop_back(); printDeque(d1); //头删 d1.pop_front(); printDeque(d1); } void test02() { deque<int> d1; d1.push_back(10); d1.push_back(20); d1.push_front(100); d1.push_front(200); printDeque(d1); //insert插入 d1.insert(d1.begin(), 1000); printDeque(d1); d1.insert(d1.begin(), 2, 2000); //头部插入2个2000 printDeque(d1); //按照区间进行插入 deque<int>d2; d2.push_back(1); d2.push_back(2); d2.push_back(3); d1.insert(d1.begin(), d2.begin(), d2.end()); //指定位置插入区间 printDeque(d1); } void test03() { deque<int> d1; d1.push_back(10); d1.push_back(20); d1.push_front(100); d1.push_front(200); printDeque(d1); //删除 deque<int>::iterator it = d1.begin(); it++; d1.erase(it); //第二个元素 printDeque(d1); //按区间方式删除 d1.erase(d1.begin(), d1.end()); printDeque(d1); //清空 d1.clear(); printDeque(d1); } int main() { test03(); system("pause"); return 0; }
3.3.6 deque 数据存取
功能描述:对deque 中的数据的存取操作
函数原型:
at(int idx);
//返回索引idx所指的数据
operator[];
//返回索引idx所指的数据
front();
//返回容器中第一个数据元素
back();
//返回容器中最后一个数据元素
#include<iostream> using namespace std; #include<deque> //deque容器 数据存取 void test01() { deque<int> d1; d1.push_back(10); d1.push_back(20); d1.push_back(30); d1.push_front(100); d1.push_front(200); d1.push_front(300); //通过[]方式访问元素 for (int i = 0; i < d1.size(); i++) { cout << d1[i] << " "; } cout << endl; //通过at方式访问元素 for (int i = 0; i < d1.size(); i++) { cout << d1.at(i) << " "; } cout << endl; cout << "第一个元素:" << d1.front() << endl; cout << "最后一个元素:" << d1.back() << endl; } int main() { test01(); system("pause"); return 0; }
300 200 100 10 20 30 300 200 100 10 20 30 第一个元素:300 最后一个元素:30 请按任意键继续. . .
3.3.7 deque 排序
功能描述:利用算法实现对deque容器进行排序
算法:sort(iterator beg, iterator end)
//对beg和end区间内元素进行排序
#include<iostream> using namespace std; #include<deque> #include<algorithm> //标准算法的头文件 //deque容器 排序 void printDeque(const deque<int>& d) { for (deque<int>::const_iterator it = d.begin(); it != d.end(); it++) { cout << *it << " "; } cout << endl; } void test01() { deque<int>d; d.push_back(10); d.push_back(20); d.push_back(30); d.push_front(100); d.push_front(200); d.push_front(300); printDeque(d); //排序 //对于支持随机访问的迭代器的容器 都可以利用sort排序 //vector容器也可以 sort(d.begin(), d.end()); //默认升序 cout << "排序后:" << endl; printDeque(d); } int main() { test01(); system("pause"); return 0; }
300 200 100 10 20 30 排序后: 10 20 30 100 200 300 请按任意键继续. . .
3.4 案例-评委打分
案例描述
有5名选手:选手ABCDE,10个评委分别对每一名选手打分,去除最高分,去除评委中最低分,取平均分。
实现步骤
1、创建五名选手,放到vector中
2、遍历vector容器,取出来每一个选手,执行for循环,可以把10个评分打分存到deque容器中
3、sort算法对deque容器中分数排序,去除最高和最低分
4、deque容器遍历一遍,累加总分
5、获取平均分
#include<iostream> using namespace std; #include<vector> #include<deque> #include<string> #include<algorithm> //标准算法的头文件 #include<ctime> class Person { public: Person(string name, int score) { this->m_Name = name; this->m_Score = score; } string m_Name; //姓名 int m_Score; //平均分 }; void createPerson(vector<Person>& v) { //引用方式传入 string nameSeed = "ABCDE"; for (int i = 0; i < 5; i++) { string name = "选手"; name += nameSeed[i]; int score = 0; Person p(name, score); //将创建的Person对象放入容器中 v.push_back(p); } } //打分 void setScore(vector<Person>& v) { for (vector<Person>::iterator it = v.begin(); it != v.end(); it++) { //将评委的分数 放入到deque容器中 deque<int>d; for (int i = 0; i < 10; i++) { int score = rand() % 41 + 60; //60~100 d.push_back(score); } cout << "选手:" << it->m_Name << "\n打分:" << endl; for (deque<int>::iterator dit = d.begin(); dit != d.end(); dit++) { cout << *dit << " "; } cout << endl; //排序 sort(d.begin(), d.end()); //去除最高分和最低分 d.pop_back(); d.pop_front(); //取平均分 int sum = 0; for (deque<int>::iterator dit = d.begin(); dit != d.end(); dit++) { sum += *dit; //累加分数 } int avg = sum / d.size(); //将平均分赋值给选手 it->m_Score = avg; } } void test01() { //随机数种子 srand((unsigned int)time(NULL)); //1、创建5名选手 vector<Person>v; createPerson(v); //2、给5名选手打分 setScore(v); //3、显示最后得分 cout << "\n最终:" << endl; for (vector<Person>::iterator it = v.begin(); it != v.end(); it++) { cout << "姓名:" << (*it).m_Name << " 分数:" << (*it).m_Score << endl; } } int main() { test01(); system("pause"); return 0; }
选手:选手A 打分: 89 65 91 85 76 62 81 79 88 80 选手:选手B 打分: 93 91 88 73 96 90 90 87 87 88 选手:选手C 打分: 92 77 95 94 88 96 83 78 78 70 选手:选手D 打分: 91 86 93 84 70 79 79 90 77 95 选手:选手E 打分: 91 68 76 95 70 83 83 67 92 69 最终: 姓名:选手A 分数:80 姓名:选手B 分数:89 姓名:选手C 分数:85 姓名:选手D 分数:84 姓名:选手E 分数:79 请按任意键继续. . .
3.5 stack容器
3.5.1 stack 基本概念
概念:stack是一种先进后出(First In Last Out,FILO)的数据结构,它只有一个出口
栈中只有顶端的元素才可以被外界使用,因此栈不允许有遍历行为
栈中进入数据称为 — 入栈push
栈中弹出数据称为 — 出栈pop
3.5.2 stack 常用接口
功能描述:栈容器常用的对外接口
构造函数:
stack<T> stk;
//stack采用模板类实现, stack对象的默认构造形式
stack(const stack &stk);
//拷贝构造函数
赋值操作:
stack& operator=(const stack &stk);
//重载等号操作符
数据存取:
push(elem);
//向栈顶添加元素
pop();
//从栈顶移除第一个元素
top();
//返回栈顶元素
大小操作:
empty();
//判断堆栈是否为空
size();
//返回栈的大小
#include<iostream> using namespace std; #include<stack> //栈stack容器 void test01() { //特点:符合先进后出数据结构 stack<int>s; //入栈 s.push(10); s.push(20); s.push(30); s.push(40); cout << "栈的大小:" << s.size() << endl; //只要栈不为空,查看栈顶,并且执行出栈操作 while (!s.empty()) { //查看栈顶元素 cout << "栈顶元素为:" << s.top() << endl; //出栈 s.pop(); } cout << "栈的大小:" << s.size() << endl; } int main() { test01(); system("pause"); return 0; }
栈的大小:4 栈顶元素为:40 栈顶元素为:30 栈顶元素为:20 栈顶元素为:10 栈的大小:0 请按任意键继续. . .
3.6 queue 容器
3.6.1 queue 基本概念
概念:Queue(队列)是一种先进先出(First In First Out,FIFO)的数据结构,它有两个出口
队列容器允许从一端新增元素,从另一端移除元素
队列中只有队头和队尾才可以被外界使用,因此队列不允许有遍历行为
队列中进数据称为 — 入队push
队列中出数据称为 — 出队pop
3.6.2 queue 常用接口
功能描述:栈容器常用的对外接口
构造函数:
queue<T> que;
//queue采用模板类实现,queue对象的默认构造形式
queue(const queue &que);
//拷贝构造函数
赋值操作:
queue& operator=(const queue &que);
//重载等号操作符
数据存取:
push(elem);
//往队尾添加元素
pop();
//从队头移除第一个元素
back();
//返回最后一个元素
front();
//返回第一个元素
大小操作:
empty();
//判断堆栈是否为空
size();
//返回栈的大小
#include<iostream> using namespace std; #include<queue> //queue队列 class Person { public: Person(string name, int age) { this->m_Name = name; this->m_Age = age; } string m_Name; int m_Age; }; void test01() { //创建队列 queue<Person>q; //准备数据 Person p1("张三", 18); Person p2("李四", 20); Person p3("王五", 22); Person p4("赵六", 24); //入队 q.push(p1); q.push(p2); q.push(p3); q.push(p4); cout << "队列大小为:" << q.size() << endl; //判断只要队列不为空 查看对头 查看对尾 出队 while (!q.empty()) { //查看对头 cout << "对头元素----姓名:" << q.front().m_Name << " 年龄:" << q.front().m_Age << endl; //查看对尾 cout << "对头元素----姓名:" << q.back().m_Name << " 年龄:" << q.back().m_Age << endl; cout << "\n"; //出队 q.pop(); } cout << "队列大小为:" << q.size() << endl; } int main() { test01(); system("pause"); return 0; }
队列大小为:4 对头元素----姓名:张三 年龄:18 对头元素----姓名:赵六 年龄:24 对头元素----姓名:李四 年龄:20 对头元素----姓名:赵六 年龄:24 对头元素----姓名:王五 年龄:22 对头元素----姓名:赵六 年龄:24 对头元素----姓名:赵六 年龄:24 对头元素----姓名:赵六 年龄:24 队列大小为:0 请按任意键继续. . .
3.7 list容器
3.7.1 list基本概念
功能:将数据进行链式存储
链表(list)是一种物理存储单元上非连续的存储结构,数据元素的逻辑顺序是通过链表中的指针链接实现的
链表的组成:链表由一系列结点组成
结点的组成:一个是存储数据元素的数据域,另一个是存储下一个结点地址的指针域
STL中的链表是一个双向循环链表
由于链表的存储方式并不是连续的内存空间,因此链表list中的迭代器只支持前移和后移,属于双向迭代器
list的优点:
1、采用动态存储分配,不会造成内存浪费和溢出
2、链表执行插入和删除操作十分方便,修改指针即可,不需要移动大量元素
list的缺点:
1、链表灵活,但是空间(指针域) 和 时间(遍历)额外耗费较大
List有一个重要的性质,插入操作和删除操作都不会造成原有list迭代器的失效,这在vector是不成立的。
总结:STL中List和vector是两个最常被使用的容器,各有优缺点
3.7.2 list构造函数
功能描述:创建list容器
函数原型:
list<T> lst;
//list采用采用模板类实现,对象的默认构造形式:
list(beg,end);
//构造函数将[beg, end)区间中的元素拷贝给本身。
list(n,elem);
//构造函数将n个elem拷贝给本身。
list(const list &lst);
//拷贝构造函数。
#include<iostream> using namespace std; #include<list> //list容器构造函数 void printList(const list<int>&L) { for (list<int>::const_iterator it = L.begin(); it != L.end(); it++) { cout << *it << " "; } cout << endl; } void test01() { //创建list容器 list<int>L1; //添加数据 L1.push_back(10); L1.push_back(20); L1.push_back(30); L1.push_back(40); //遍历容器 printList(L1); //2、区间方式构造 list<int>L2(L1.begin(), L1.end()); printList(L2); //3、拷贝构造 list<int>L3(L2); printList(L3); //4、n个elem list<int>L4(10, 100); //10个100 printList(L4); } int main() { test01(); system("pause"); return 0; }
10 20 30 40 10 20 30 40 10 20 30 40 100 100 100 100 100 100 100 100 100 100 请按任意键继续. . .
总结:list构造方式同其他几个STL常用容器,熟练掌握即可
3.7.3 list 赋值和交换
功能描述:给list容器进行赋值,以及交换list容器
函数原型:
assign(beg, end);
//将[beg, end)区间中的数据拷贝赋值给本身。
assign(n, elem);
//将n个elem拷贝赋值给本身。
list& operator=(const list &lst);
//重载等号操作符
swap(lst);
//将lst与本身的元素互换。
#include<iostream> using namespace std; #include<list> //list容器 赋值和交换 void printList(const list<int>&L){ for (list<int>::const_iterator it = L.begin(); it != L.end(); it++) { cout << *it << " "; } cout << endl; } //赋值 void test01() { list<int>L1; L1.push_back(10); L1.push_back(20); L1.push_back(30); L1.push_back(40); printList(L1); list<int>L2; L2 = L1; //=赋值 printList(L2); list<int>L3; L3.assign(L2.begin(), L2.end()); printList(L3); list<int>L4; L4.assign(10, 100); printList(L4); } //交换 void test02() { list<int>L1; L1.push_back(10); L1.push_back(20); L1.push_back(30); L1.push_back(40); list<int>L2; L2.assign(10, 100); cout << "交换前:" << endl; printList(L1); printList(L2); L1.swap(L2); cout << "交换后:" << endl; printList(L1); printList(L2); } int main() { test02(); system("pause"); return 0; }
交换前: 10 20 30 40 100 100 100 100 100 100 100 100 100 100 交换后: 100 100 100 100 100 100 100 100 100 100 10 20 30 40 请按任意键继续. . .
3.7.4 list 大小操作
功能描述:对list容器的大小进行操作
函数原型:
size();
//返回容器中元素的个数
empty();
//判断容器是否为空
resize(num);
//重新指定容器的长度为num,若容器变长,则以默认值填充新位置。
//如果容器变短,则末尾超出容器长度的元素被删除。
resize(num, elem);
//重新指定容器的长度为num,若容器变长,则以elem值填充新位置。
//如果容器变短,则末尾超出容器长度的元素被删除。
#include<iostream> using namespace std; #include<list> //list容器 大小操作 void printList(const list<int>& L) { for (list<int>::const_iterator it = L.begin(); it != L.end(); it++) { cout << *it << " "; } cout << endl; } void test01() { list<int>L1; L1.push_back(10); L1.push_back(20); L1.push_back(30); L1.push_back(40); printList(L1); //判断容器是否为空 if (L1.empty()) { cout << "L1为空" << endl; } else { cout << "L1不为空" << endl; cout << "L1的元素个数:" << L1.size() << endl; } L1.resize(10, 222); //222填充到10个 printList(L1); L1.resize(2); printList(L1); L1.clear(); } int main() { test01(); system("pause"); return 0; }
10 20 30 40 L1不为空 L1的元素个数:4 10 20 30 40 222 222 222 222 222 222 10 20 请按任意键继续. . .
3.7.5 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值匹配的元素
#include<iostream> using namespace std; #include<list> //list容器 插入和删除 void printList(const list<int>& L) { for (list<int>::const_iterator it = L.begin(); it != L.end(); it++) { cout << *it << " "; } cout << endl; } void test01() { list<int>L1; //尾插 L1.push_back(10); L1.push_back(20); L1.push_back(30); //头插 L1.push_front(100); L1.push_front(200); L1.push_front(300); printList(L1); //尾删 L1.pop_back(); //头删 L1.pop_front(); printList(L1); //insert插入 list<int>::iterator it = L1.begin(); it++; L1.insert(it, 1000); printList(L1); //删除 it = L1.begin(); L1.erase(it); printList(L1); //移除 L1.push_back(10); //移除所有的10 printList(L1); L1.remove(10); printList(L1); L1.clear(); } int main() { test01(); system("pause"); return 0; }
300 200 100 10 20 30 200 100 10 20 200 1000 100 10 20 1000 100 10 20 1000 100 10 20 10 1000 100 20 请按任意键继续. . .
3.7.6 list 数据存取
函数原型:
front();
//返回第一个元素。
back();
//返回最后一个元素。
注意:不支持at和[]访问数据
#include<iostream> using namespace std; #include<list> //list容器 数据存取 void test01() { list<int>L1; //尾插 L1.push_back(10); L1.push_back(20); L1.push_back(30); L1.push_back(40); //L1[0]; //不支持,list无序 //L1.at(0); cout << "第一个元素:" << L1.front() << endl; cout << "最后一个元素:" << L1.back() << endl; //验证迭代器是不支持随机访问的 list<int>::iterator it = L1.begin(); it++; it--; //it = it + 2; //不支持随机访问 ,只支持++和-- 双向访问 } int main() { test01(); system("pause"); return 0; }
第一个元素:10 最后一个元素:40 请按任意键继续. . .
3.7.7 list 反转和排序
函数原型:
reverse();
//反转链表
sort();
//链表排序
#include<iostream> using namespace std; #include<list> //#include<algorithm> //list容器 数据存取 void printList(const list<int>& L) { for (list<int>::const_iterator it = L.begin(); it != L.end(); it++) { cout << *it << " "; } cout << endl; } bool myCompare(int v1, int v2) { //降序 第一个数 > 第二个数 return v1 > v2; } void test01() { list<int>L1; L1.push_back(20); L1.push_back(10); L1.push_back(50); L1.push_back(40); L1.push_back(30); printList(L1); //排序 升序 //sort(L1.begin(), L1.end()); //错的,因为无序 L1.sort(); //成员函数, 默认升序 printList(L1); //反转 L1.reverse(); printList(L1); //降序 L1.sort(myCompare); printList(L1); } int main() { test01(); system("pause"); return 0; }
20 10 50 40 30 10 20 30 40 50 50 40 30 20 10 50 40 30 20 10 请按任意键继续. . .
3.7.8 排序案例
案例描述:将Person自定义数据类型进行排序,Person中属性有姓名、年龄、身高
排序规则:按照年龄进行升序,如果年龄相同按照身高进行降序
#include<iostream> using namespace std; #include<list> #include<string> class Person { public: Person(string name, int age, int height) { this->m_Name = name; this->m_Age = age; this->m_Height = height; } string m_Name; int m_Age; int m_Height; }; //指定排序规则 bool comparePerson(Person&p1, Person&p2) { //按照年龄升序 if (p1.m_Age == p2.m_Age) { //按照身高降序 return p1.m_Height < p2.m_Height; } else { return p1.m_Age < p2.m_Age; } } void test01() { list<Person>L; //创建容器 Person p1("刘备", 35, 175); Person p2("曹操", 45, 180); Person p3("孙权", 40, 170); Person p4("赵云", 25, 190); Person p5("张飞", 35, 160); Person p6("关羽", 35, 200); //插入数据 L.push_back(p1); L.push_back(p2); L.push_back(p3); L.push_back(p4); L.push_back(p5); L.push_back(p6); for (list<Person>::iterator it = L.begin(); it != L.end(); it++) { cout << "姓名:" << (*it).m_Name << " 年龄:" << it->m_Age << " 身高:" << it->m_Height << endl; } //排序 cout << "-----------------------------------" << endl; cout << "排序后:" << endl; L.sort(comparePerson); for (list<Person>::iterator it = L.begin(); it != L.end(); it++) { cout << "姓名:" << (*it).m_Name << " 年龄:" << it->m_Age << " 身高:" << it->m_Height << endl; } } int main() { test01(); system("pause"); return 0; }
姓名:刘备 年龄:35 身高:175 姓名:曹操 年龄:45 身高:180 姓名:孙权 年龄:40 身高:170 姓名:赵云 年龄:25 身高:190 姓名:张飞 年龄:35 身高:160 姓名:关羽 年龄:35 身高:200 ----------------------------------- 排序后: 姓名:赵云 年龄:25 身高:190 姓名:张飞 年龄:35 身高:160 姓名:刘备 年龄:35 身高:175 姓名:关羽 年龄:35 身高:200 姓名:孙权 年龄:40 身高:170 姓名:曹操 年龄:45 身高:180 请按任意键继续. . .
3.8 set/ multiset 容器
3.8.1 set基本概念
简介:所有元素都会在插入时自动被排序
本质:set/multiset属于关联式容器,底层结构是用二叉树实现。
set和multiset区别:
- set不允许容器中有重复的元素
- multiset允许容器中有重复的元素
3.8.2 set构造和赋值
功能描述:创建set容器以及赋值
构造:
set<T> st;
//默认构造函数:
set(const set &st);
//拷贝构造函数
赋值:
set& operator=(const set &st);
//重载等号操作符
#include<iostream> using namespace std; #include<set> //set容器 构造和赋值 void printSet(set<int>& s) { for (set<int>::iterator it = s.begin(); it != s.end(); it++) { cout << *it << " "; } cout << endl; } void test01() { set<int>s1; //插入数据 s1.insert(10); s1.insert(40); s1.insert(30); s1.insert(20); s1.insert(30); //遍历容器 //set容器特点:有序(升序) 无重复元素 printSet(s1); //2、拷贝构造 set<int>s2(s1); printSet(s2); //3、赋值 set<int>s3; s3 = s2; printSet(s3); } int main() { test01(); system("pause"); return 0; }
10 20 30 40 10 20 30 40 10 20 30 40 请按任意键继续. . .
总结:
1、set容器插入数据时用insert
2、set容器插入数据的数据会自动排序
3.8.3 set大小和交换
函数原型:
size();
//返回容器中元素的数目
empty();
//判断容器是否为空
swap(st);
//交换两个集合容器
#include<iostream> using namespace std; #include<set> void printSet(set<int>& s) { for (set<int>::iterator it = s.begin(); it != s.end(); it++) { cout << *it << " "; } cout << endl; } void test01() { set<int>s1; //插入数据 s1.insert(10); s1.insert(40); s1.insert(30); s1.insert(20); s1.insert(30); if (s1.empty()) { cout << "s1为空" << endl; } else { cout << "s1不为空" << endl; cout << "s1的大小为:" << s1.size() << endl; } } void test02() { set<int>s1; s1.insert(10); s1.insert(40); s1.insert(30); s1.insert(20); s1.insert(30); set<int>s2; s2.insert(100); s2.insert(200); s2.insert(300); cout << "交换前:" << endl; printSet(s1); printSet(s2); s1.swap(s2); cout << "交换后:" << endl; printSet(s1); printSet(s2); } int main() { test02(); system("pause"); return 0; }
交换前: 10 20 30 40 100 200 300 交换后: 100 200 300 10 20 30 40 请按任意键继续. . .
3.8.4 set插入和删除
函数原型:
insert(elem);
//在容器中插入元素。
clear();
//清除所有元素
erase(pos);
//删除pos迭代器所指的元素,返回下一个元素的迭代器。
erase(beg, end);
//删除区间[beg,end)的所有元素 ,返回下一个元素的迭代器。
erase(elem);
//删除容器中值为elem的元素。
#include<iostream> using namespace std; #include<set> //set容器 插入和删除 void printSet(set<int>& s) { for (set<int>::iterator it = s.begin(); it != s.end(); it++) { cout << *it << " "; } cout << endl; } void test01() { set<int>s1; //插入数据 s1.insert(10); s1.insert(20); s1.insert(30); s1.insert(40); s1.insert(30); printSet(s1); //删除指定元素 s1.erase(s1.begin()); printSet(s1); s1.erase(30); printSet(s1); s1.erase(s1.begin(), s1.end()); printSet(s1); //清空 s1.clear(); } int main() { test01(); system("pause"); return 0; }
10 20 30 40 20 30 40 20 40 请按任意键继续. . .
3.8.5 set查找和统计
函数原型:
find(key);
//查找key是否存在,若存在,返回该键的元素的迭代器;若不存在,返回set.end();
count(key);
//统计key的元素个数
#include<iostream> using namespace std; #include<set> //set容器 查找和统计 void test01() { set<int>s1; //插入数据 s1.insert(10); s1.insert(20); s1.insert(30); s1.insert(40); s1.insert(30); //查找 set<int>::iterator pos = s1.find(30); if (pos != s1.end()) { cout << "找到元素:" << *pos << endl; } else { cout << "未找到元素" << endl; } //统计 int number = s1.count(30); //要么为1 要么为0 cout << "number = " << number << endl; } int main() { test01(); system("pause"); return 0; }
找到元素:30 number = 1 请按任意键继续. . .
3.8.6 set和multiset区别
区别:
- set不可以插入重复数据,而multiset可以
- set插入数据的同时会返回插入结果,表示插入是否成功
- multiset不会检测数据,因此可以插入重复数据
#include<iostream> using namespace std; #include<set> //set容器 multiset容器 区别 void printSet(multiset<int>& s) { for (multiset<int>::iterator it = s.begin(); it != s.end(); it++) { cout << *it << " "; } cout << endl; } void test01() { set<int>s; pair<set<int>::iterator, bool> ret = s.insert(10); if (ret.second) { cout << "第一次插入成功" << endl; } else { cout << "第一次插入失败" << endl; } ret = s.insert(10); if (ret.second) { cout << "第二次插入成功" << endl; } else { cout << "第二次插入失败" << endl; } cout << "\n"; multiset<int>s1; //插入数据 s1.insert(10); s1.insert(20); s1.insert(30); s1.insert(40); s1.insert(30); printSet(s1); //有序 允许重复元素 } int main() { test01(); system("pause"); return 0; }
第一次插入成功 第二次插入失败 10 20 30 30 40 请按任意键继续. . .
3.8.7 pair对组创建
功能描述:成对出现的数据,利用对组可以返回两个数据
两种创建方式:
pair<type, type> p ( value1, value2 );
pair<type, type> p = make_pair( value1, value2 );
#include<iostream> using namespace std; //pair对组 的创建 void test01() { //第一种方式 pair<string, int>p("Tom", 20); cout << "姓名:" << p.first << "\t年龄:" << p.second << endl; //第二种 pair<string, int>p2 = make_pair("张三", 22); cout << "姓名:" << p2.first << "\t年龄:" << p2.second << endl; } int main() { test01(); system("pause"); return 0; }
姓名:Tom 年龄:20 姓名:张三 年龄:22 请按任意键继续. . .
3.8.8 set容器排序
学习目标:set容器默认排序规则为从小到大,掌握如何改变排序规则
主要技术点:利用仿函数,可以改变排序规则
#include<iostream> using namespace std; #include<set> //set容器排序 class MyCompare { public: bool operator()(int v1, int v2) const //为什么2019要加const? { return v1 > v2; } }; void test01() { set<int>s1; s1.insert(10); s1.insert(40); s1.insert(20); s1.insert(50); s1.insert(30); for (set<int>::iterator it = s1.begin(); it != s1.end(); it++) { cout << *it << " "; } cout << endl; //指定排序规则 从大到小 set<int, MyCompare>s2; s2.insert(10); s2.insert(40); s2.insert(20); s2.insert(50); s2.insert(30); for (set<int, MyCompare>::iterator it = s2.begin(); it != s2.end(); it++) { cout << *it << " "; } cout << endl; } int main() { test01(); system("pause"); return 0; }
10 20 30 40 50 50 40 30 20 10 请按任意键继续. . .
示例二 set存放自定义数据类型
#include<iostream> using namespace std; #include<set> //set容器排序 存放自定义数据类型 class Person { public: Person(string name, int age) { this->m_Name = name; this->m_Age = age; } string m_Name; int m_Age; }; class comparePerson { public: bool operator()(const Person& p1, const Person& p2) const { //按照年龄 降序 return p1.m_Age > p2.m_Age; } }; void test01() { set<Person, comparePerson>s; //自定义数据类型需要指定排序规则 //创建Person对象 Person p1("张三", 18); Person p2("李四", 20); Person p3("王五", 22); Person p4("赵六", 24); s.insert(p1); s.insert(p2); s.insert(p3); s.insert(p4); for (set<Person, comparePerson>::iterator it = s.begin(); it != s.end(); it++) { cout << "姓名:" << it->m_Name << "\t年龄:" << it->m_Age << endl; } } int main() { test01(); system("pause"); return 0; }
姓名:赵六 年龄:24 姓名:王五 年龄:22 姓名:李四 年龄:20 姓名:张三 年龄:18 请按任意键继续. . .