我们继续来介绍STL的相关容器的使用
一、vector
vector 是将元素置于一个动态数组中加以管理的容器
vector 可以随机存取元素 (用 [] 操作符 或 at () 方法)
vector 尾部添加或移除元素非常快速,但是在中部和头部时比较费时
1、vector 数据的访问
void func1()
{
vector<int> v;
v.push_back(1);
v.push_back(2);
v.push_back(6);
// 第一个元素
cout << v.front() << endl;
// 最后一个元素
cout << v.back() << endl;
// 返回值是一个引用
v.front() = 10;
v.back() = 8;
while(!v.empty())
{
cout << v.back() << endl;
// 删除最后一个元素,没有返回值
v.pop_back();
}
}
2、遍历
void printV(vector<int> &v1)
{
for (vector<int>::iterator it = v1.begin(); it != v1.end(); it++)
{
cout << *it << " ";
}
cout << endl;
}
3、构造
void func2()
{
// 定义一个容器,一开始赋予10个对象空间
vector<int> v1(10);
cout << "当前元素个数: " << v1.size() << endl;
v1[0] = 17;
v1.at(1) = 9;
v1.push_back(7);
cout << "当前元素个数: " << v1.size() << endl;
printV(v1);
vector<int> v2(10, 2);
printV(v2);
vector<int> v3 = v2;
printV(v3);
v3 = v1;
printV(v3);
vector<int> v4(v3.begin(), v3.begin()+4);
printV(v4);
}
4、元素删除
void func3()
{
vector<int> v1;
for (int i = 0; i < 10; i++)
{
v1.push_back(i);
}
printV(v1);
vector<int>::iterator it = find(v1.begin(), v1.end(), 5);
// 单个元素删除
v1.erase(it);
printV(v1);
vector<int>::iterator it1 = find(v1.begin(), v1.end(), 3);
vector<int>::iterator it2 = find(v1.begin(), v1.end(), 8);
// 区间删除
v1.erase(it1, it2);
printV(v1);
// 清空容器
// v1.clear();
vector<int> v2; // 空的容器
// 容器交换
v1.swap(v2);
v1.push_back(1);
v1.push_back(2);
v1.push_back(2);
v1.push_back(6);
v1.push_back(2);
v1.push_back(2);
//for(vector<int>::iterator it = v1.begin(); it != v1.end();)
//{
// if (*it == 2)
// {
// // 返回指向删除元素下一个元素的迭代器,需要接收回来
// it = v1.erase(it);
// }
// else
// {
// it ++;
// }
//
//}
it = v1.begin();
while(it != v1.end())
{
if (*it == 2)
it = v1.erase(it);
else
it++;
}
printV(v1);
}
5、元素插入
void func4()
{
vector<int> v;
v.push_back(1);
v.push_back(2);
v.push_back(6);
v.insert(v.begin(), 10);
printV(v);
v.insert(v.begin()+2, 3);
printV(v);
v.insert(v.end(), 4);
printV(v);
vector<int> v1;
v1.insert(v1.begin(), v.begin(), v.end());
printV(v1);
}
二、stack 和 queue
stack是堆栈容器,是一种“先进后出”的容器
queue是队列容器,是一种“先进先出”的容器
栈这个容器的相关操作
void func1()
{
stack<int> s;
s.push(1);
s.push(5);
s.push(3);
s.push(10); //插入
cout << "栈顶元素: " << s.top() << endl;
cout << "元素个数: " << s.size() << endl;
while (!s.empty())
{
cout << s.top() << endl; // 打印栈顶元素
s.pop();
}
}
队列的相关操作(和栈类似)
void func2()
{
queue<int> q;
q.push(1);
q.push(10);
q.push(2);
q.push(5);
cout << "队头元素: " << q.front() << endl;
cout << "队尾个数: " << q.back() << endl;
while (!q.empty())
{
cout << q.front() << endl; // 打印栈顶元素
q.pop();
}
}
用两个栈实现一个队列
class MyQueue
{
public:
// 出队
void pop()
{
// 第一种:
// 1、先把 s1 留一个元素, 其他导入到 s2 中
// 2、s1 出栈
// 3、将 s2 元素再导入到 s1 中
// 第二种
// 1、先判断 s2 是否为空
// 2、不为空,s2直接出栈
// 3、如果空,将 s1 留一个元素, 其他导入到 s2 中
// 4、s1出栈
if(s2.empty())
{
while (s1.size() > 1)
{
s2.push(s1.top());
s1.pop();
}
if (!s1.empty())
s1.pop();
}
else
{
s2.pop();
}
}
// 入队
void push(int num)
{
// 入 s1
s1.push(num);
}
private:
stack<int> s1;
stack<int> s2;
};
list是一个双向链表容器,可以高效地进行插入和删除
list不可以随机的存储元素
1、list 的赋值 删除 反序
void func1()
{
list<int> list1;
list1.push_back(1);
list1.push_back(2);
list1.push_back(2);
list1.push_back(2);
list1.push_back(2);
list1.push_back(2);
list1.push_back(2);
list1.push_back(3);
list1.push_front(-1);
list1.push_front(-2);
list1.push_front(-3);
printL(list1);
list<int>::iterator it = list1.begin();
it++;
it++;
// list1.erase(list1.begin(), list1.end()); 删除区间数据返回下一个数据的位置
//list1.erase(list1.begin(), list1.begin());
//printL(list1);
list1.remove(2); //删除匹配的元素
printL(list1);
list1.reverse(); //反序列表
printL(list1);
}
2、list 与 迭代器
void func2()
{
vector<int> v(10);
for (int i = 0; i < 10; i++)
{
v[i] = i;
}
// 正向迭代器
for(vector<int>::iterator it = v.begin(); it != v.end(); it++)
{
cout << *it << " ";
}
cout << endl;
// 反向迭代器
for(vector<int>::reverse_iterator it = v.rbegin(); it != v.rend(); it++)
{
cout << *it << " ";
}
cout << endl;
}
四、优先级队列 priority_queue
优先级队列内部数据是排完序的,默认是从大到小排序
void func1()
{
// 优先级队列内部数据是排完序的,默认是从大到小排序
// priority_queue<int> q;
// priority_queue<int, vector<int>, less<int>> q;
priority_queue<int, vector<int>, greater<int>> q;
q.push(10);
q.push(4);
q.push(2);
q.push(65);
while (!q.empty())
{
cout << q.top() << endl;
q.pop();
}
}
五、set/multiset
set 是一个集合容器,其中所包含的元素是唯一的,集合中的元素按一定顺序排列
元素插入过程是按排序规则插入,所以不能指定插入位置
multiset与set的区别:set支持唯一键值,每个元素值只能出现一次;
而multiset中同一值可以出现多次。
set.insert(elem); //在容器中插入元素。
set.begin(); //返回容器中第一个数据的迭代器。
set.end(); //返回容器中最后一个数据之后的迭代器。
set.rbegin(); //返回容器中倒数第一个元素的迭代器。
set.rend(); //返回容器中倒数最后一个元素的后面的迭代器。
set<int,less<int> > setIntA; //该容器是按升序方式排列元素。
set<int,greater<int>> setIntB; //该容器是按降序方式排列元素。
六、map/multimap
map的使用 容器:存的是键 值 对
map 和 set 一样会自动排序,是以键进行排序 ,map 键唯一
通过 map 插入有3种方式
void func1()
{
// 键 : int 类型
// 值 : string 类型
// 存学生的 id 和 姓名
map<int, string> m;
// 数据插入:
// 1、通过 pair 键值对插入数据
m.insert(pair<int, string>(7, "郑"));
m.insert(pair<int, string>(8, "王"));
// 2、通过 make pair 构建键值对
m.insert(make_pair(5, "周"));
m.insert(make_pair(1, "赵"));
// 3、通过map类型插入
m.insert(map<int, string>::value_type(3, "孙"));
m.insert(map<int, string>::value_type(2, "钱"));
// 4、通过 [] 方式插入数据, []不代表数组下标,[]内部的值是 map 键
m[4] = "李";
m[6] = "吴";
printM(m);
}
还有一种方式是通过 [ ] 方式插入数据,[ ] 不代表数组下标, [ ] 内部的值是 map 键
添加用户(这个用户是类呢)
class Student
{
public:
Student(int id, string name)
{
this->id = id;
this->name = name;
}
private:
int id;
string name;
};
class UserManager
{
public:
UserManager()
{
}
// 添加用户
void add(int id, string name)
{
Student *ps = new Student(id, name);
m.insert(pair<string, Student*>(name, ps));
}
~UserManager()
{
map<string, Student*>::iterator it = m.begin();
while(it != m.end())
{
delete it->second;
it = m.erase(it);
}
}
private:
// 键: 学生名字 值 : 学生
map<string, Student*> m;
};
map 迭代器的删除和查找
// 迭代器删除
m.erase(m.begin());
printM(m);
// 通过键删除数据
cout << "-----------------" << endl;
m.erase("赵");
printM(m);
cout << "-----------------" << endl;
// 查找数据: 查找通过键查找
map<string, int>::iterator it = m.find("孙");
if (it != m.end())
{
cout << "id = " << it->second << endl;
}
pair<map<string, int>::iterator, map<string, int>::iterator> ret = m.equal_range("孙");
if (ret.first != m.end())
cout << "id = " << ret.first->second << endl;
if (ret.second != m.end())
cout << "id = " << ret.second->second << endl;
}
void func4()
{
map<string, int> m1;
m1.insert(make_pair("王", 8));
// [] 不一定是插入
// 如果键存在,修改原键的值,如果键不存在,就创建一个新的键值对
m1["张"] = 10;
}
multimap与map的区别:map支持唯一键值,每个键只能出现一次;
而multimap中相同键可以出现多次。multimap不支持[]操作符。