c++容器 stl
vector
set
map
vector | deque | list | set | multiset | map | multimap | |
---|---|---|---|---|---|---|---|
典型存储结构 | 单端数组 | 双端数组 | 双向链表 | 二叉树 | 二叉树 | 二叉树 | 二叉树 |
可随机存取 | 是 | 是 | 否 | 否 | 否 | 对key而言 是 | 否 |
元素搜寻速度 | 慢 | 慢 | 非常慢 | 快 | 快 | 对key而言 快 | 对key而言 快 |
快速安插移除 | 尾端 | 头尾两端 | 任何位置 | - | - | - | - |
vector
1.插入、遍历、查找、删除
#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
using namespace std;
#include<vector>
#include<algorithm>
int main() {
//插入
vector<int> v1;
v1.push_back(1);
v1.push_back(2);
v1.push_back(3);
v1.push_back(4);
vector<int> v2;
v2.push_back(22);
//在v2尾部插入v1
v2.insert(v2.end(),v1.begin(),v1.end());
//遍历
for (vector<int>::iterator it = v1.begin(); it != v1.end(); it++) {
cout << *it << " ";
}
cout << endl;
//查找
vector<int>::iterator it = find(v2.begin(), v2.end(), 55);
if (it != v2.end()) {
cout << *it << endl;
}
else {
cout << "inexistence" << endl;
}
//排序 需要引用 #include<algorithm> 包
sort(v2.begin(), v2.end());//升序
sort(v2.rbegin(), v2.rend());//降序
//删除
v1.pop_back();//弹出最后的
//erase
vector<int>::iterator it2 = find(v2.begin(), v2.end(), 2);
v2.erase(it2);//删除一个
v2.erase(v2.begin(), v2.end());//全部删除
cout << v2.size() << endl;
}
注意:
如果放的是类,类中有指针。需要重写 拷贝构造函数。否则,在系统结束释放时,会报错。
因为,容器添加类都是复制的。
容器执行插入元素的操作时,内部实施拷贝动作
所以STL容器内存储的元素必须 能够被拷贝(必须提供拷贝构造函数)
例子:
#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
using namespace std;
#include<vector>
class Teacher {
public:
Teacher(const char* name, int age) {
this->name = new char[strlen(name) + 1];
strcpy(this->name, name);
this->age = age;
}
~Teacher() {
if (name != NULL) {
delete [] name;
name = NULL;
age = 0;
}
}
//Teacher t2=t1 如果不重写拷贝构造函数,在系统结束释放时,会报错。
Teacher(const Teacher &obj) {
this->name = new char[strlen(obj.name) + 1];
strcpy(this->name, obj.name);
this->age = obj.age;
}
void printT() {
cout << name << "->" << age << endl;
}
private:
char* name;
int age;
};
int main() {
Teacher t1("w1", 31);
vector<Teacher> v1;
v1.push_back(t1);
v1[0].printT();
return 0;
}
v1.push_back(t1);
这一步会复制一个class,会走 Teacher(const Teacher &obj)
拷贝构造函数
最好 重载 =号操作符 t3=t2=t1
因为当 出现 t3=t2
也有类似的问题。
public;
//重载 =号操作符 t3=t2=t1
Teacher& operator=(const Teacher &obj) {
if (name != NULL) {
delete[] name;
name = NULL;
age = 0;
}
this->name = new char[strlen(obj.name) + 1];
strcpy(this->name, obj.name);
this->age = obj.age;
return *this;
}
set
multiset可以存在相同的
int main() {
//插入
set<int> set1;
set1.insert(1);
set1.insert(2);
set1.insert(3);
//遍历
for (set<int>::iterator it = set1.begin(); it != set1.end(); it++) {
cout << *it << " ";
}
cout << endl;
//查找
set<int>::iterator it1 = set1.find(1);
if (it1 != set1.end()) {
cout << *it1 << endl;
}
else {
cout << "inexistence" << endl;
}
//删除
set1.erase(2);
return 0;
}
因为set会自动排序,
所以当保存的是一个类的时候,需要写个 伪函数 来判断大小排序。
#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
using namespace std;
#include<set>
class Student {
public:
Student(const char *name, int age) {
strcpy(this->name, name);
this->age = age;
}
char name[64];
int age;
};
//仿函数
struct FuncStudent {
bool operator()(const Student& left, const Student& right) const {
if (left.age < right.age) {
return true;
}
else {
return false;
}
}
};
int main() {
//插入
set<Student,FuncStudent> set1;
Student s1("s1",10);
Student s2("s2",20);
Student s3("s3",30);
set1.insert(s1);
set1.insert(s2);
set1.insert(s3);
//遍历
for (set<Student>::iterator it = set1.begin(); it != set1.end(); it++) {
cout << it->name << ":"<<it->name<<endl;
}
//查找
set<Student>::iterator it1 = set1.find(s1);
if (it1 != set1.end()) {
cout << it1->name << ":" << it1->name << endl;
}
else {
cout << "inexistence" << endl;
}
//删除
set1.erase(it1);
return 0;
}
map
multimap可以存在相同的
1.插入、打印、删除
#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
using namespace std;
#include<map>
int main() {
map<int, string> map1;
//插入 4种
//1
map1.insert(pair<int, string>(1, "teacher01"));
map1.insert(pair<int, string>(2, "tea02"));
//2
map1.insert(make_pair(3, "tea03"));
map1.insert(make_pair(4, "tea04"));
//3
map1.insert(map<int, string>::value_type(5, "tea05"));
//4
map1[6] = "tea06";
//打印
cout << map1[5] << endl;
cout << map1[6] << endl;
for (map<int, string>::iterator it = map1.begin(); it != map1.end(); it++) {
cout << it->first << "->" << it->second << endl;
}
//删除
while (!map1.empty()) {
map<int, string>::iterator it = map1.begin();
cout << it->first << "->" << it->second << endl;
map1.erase(it);
}
cout << map1.size() << endl;
}
2.四种插入方式的区别:
3.判断是否插入成功:
#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
using namespace std;
#include<map>
int main() {
map<int, string> map1;
//插入
//pair<map<int, string>::iterator, bool> mypair
pair<map<int, string>::iterator, bool> mypair1 = map1.insert(pair<int, string>(1, "teacher01"));
map1.insert(pair<int, string>(2, "tea02"));
pair<map<int, string>::iterator, bool> mypair3 = map1.insert(make_pair(3, "tea03"));
map1.insert(make_pair(4, "tea04"));
//最终为5-》tea05,不会覆盖
pair<map<int, string>::iterator, bool> mypair5 = map1.insert(map<int, string>::value_type(5, "tea05"));
pair<map<int, string>::iterator, bool> mypair6 = map1.insert(map<int, string>::value_type(5, "tea06"));
//判断是否插入成功
if (mypair5.second != true) {
cout << "false" << endl;
}
else {
cout << mypair5.first->first << "->" << mypair5.first->second << endl;
}
if (mypair6.second != true) {
cout << "false" << endl;
}
else {
cout << mypair6.first->first << "->" << mypair6.first->second << endl;
}
//最终为7-》tea77,会覆盖
map1[7] = "tea07";
map1[7] = "tea77";
//打印
for (map<int, string>::iterator it = map1.begin(); it != map1.end(); it++) {
cout << it->first << "->" << it->second << endl;
}
//查找
//...
}
4.查找
//查找
//find
map<int, string>::iterator it2 = map1.find(100);
if (it2 == map1.end()) {
cout << "inexistence" << endl;
}
else {
cout << it2->first << "->" << it2->second << endl;
}
//equal_range
//返回两个迭代器,形成一个pair
//第一个迭代器,返回的是 >= 5 的位置
//第二个迭代器,返回的是 > 5 的位置
pair<map<int,string>::iterator, map<int, string>::iterator> mypair = map1.equal_range(5);
if (mypair.first == map1.end()) {
cout << "第一个迭代器,返回的是 >= 5 的位置 不存在" << endl;
}
else {
cout << mypair.first->first << "->" << mypair.first->second << endl;
}
if (mypair.second == map1.end()) {
cout << "第二个迭代器,返回的是 > 5 的位置 不存在" << endl;
}
else {
cout << mypair.second->first << "->" << mypair.second->second << endl;
}