判断迭代器是否双向,是否随机访问的小技巧:
list<int>::iterator it = L.begin();
it++;
it--://如果不报错,则支持双向
it = it + 1;//如果不报错,则支持随机访问
容器遍历操作:
void printVector(vector<int>$v)
{
for(vector<T>::iterator it = v.begin(); it != v.end(); it++)
{
cout << *it << endl;
}
}
1 stack容器(栈)
先进后出,栈。栈只有顶端元素能被外界使用,因此无法遍历。
stack<int>s;
s.push(elem);//入栈
s.pop();//出栈
s.empty();//空则返回true,不空返回false
s.size();//返回大小
2 queue容器(队列)
先进先出,队列。队列只有两端元素能被外界使用,因此无法遍历。
queue<int>q;
q.push(elem);//入队
q.pop();//出队
q.back();//返回最后一个元素
q.front();//返回第一个元素
q.empty();//判断是否为空
q.size();//返回大小
3 list容器(链表)
优点:可以对任意位置进行快速的插入或删除元素,动态存储分配,不会造成内存浪费和一处。
缺点:容器遍历速度没有数组快,占用空间比数组大。
链表为非连续存储结构,其逻辑顺序是通过链表中的指针实现的。
链表由一系列结点组成,结点又包括存储数据元素的数据域和存储下一个结点地址的指针域构成。
STL中的链表是一个双向循环链表,有前结点和后结点。
3.1 构造
list<int>L1;
list<int>L2(L1.begin(), L1.end());//传入区间迭代器构造
list<int>L3(L2);//拷贝构造
list<int>L4(10, 1000);// 放10个1000进去
3.2 赋值和交换
L1.push_back(elem);//尾插
L2.assign(L1.begin(),L1.end());
L3.assign(10, 100);//放10个100
L3.swap(L2);//交换L2和L3
3.3 大小操作
L1.empty();
L1.size();
L1.resize(10, 1000);//把大小变为10,用1000填充,若不指定则默认填充0
3.4 插入和删除
L.push_back(elem);//尾插
L.pop_back();//尾删
L.push_front(elem);//头插
L.po_front();//头删
list<int>::iterator it = L.begin();
L.insert(++it, 1000);//用迭代器插入
L.erase(it);//用迭代器删除
L.remove(10000); // 把所有匹配值的元素全部删掉
L.clear();//清空
3.5 数据存取
list不支持[]和at()访问,因为不是连续线性空间存储,且迭代器不支持随机访问。只能通过front和back
L.front()
L.back();
3.6 翻转和排序
由于不支持随机访问,所以不能用L.sort(it1 , it2)排序
L.reverse();//反转
L.sort();//升序排序
bool myCompare(int a, int b)
{
return a > b;
}
L.sort(myCompare);//利用了回调函数的降序排序
3.7排序例程(利用回调函数)
对自定义数据集Person按照年龄升序排序,如果年龄相同则按照身高倒序
class Person
{
public:
string m_name;
int m_age;
int m_height;
Person(string name, int age, int height)
{
m_name = name;
m_age = age;
m_height = height;
}
};
bool ComparePerson(Person& a, Person& b)
{
//如果年龄相同,则身高降序
if (a.m_age == b.m_age)
{
return a.m_height > b.m_height;
}
//年龄升序
return a.m_age < b.m_age;
}
int main()
{
// 初始化随机数生成器
std::random_device rd; // 用于获得种子
std::mt19937 gen(rd()); // 使用随机设备种子初始化Mersenne Twister生成器
std::uniform_int_distribution<int> distrib(18, 30); // 定义分布范围[10, 100]
Person p1("卢本伟",25,180);
Person p2("孙笑川",30,160);
Person p3("塔菲",30,155);
Person p4("嘉然",18,165);
Person p5("范小勤",18,140);
list<Person>l;
l.push_back(p1);
l.push_back(p2);
l.push_back(p3);
l.push_back(p4);
l.push_back(p5);
l.sort(ComparePerson);
for (list<Person>::iterator it = l.begin(); it != l.end(); it++)
{
cout << (*it).m_name << '\t' << (*it).m_age << '\t' << (*it).m_height << endl;
}
return 0;
}
4 set/multiset容器(二叉树)
所有元素都会在插入时自动被排序
set容器不允许有重复元素,multiset可以
4.1 构造和赋值
set<int>s1;
s1.insert(10);//set容器插入数据只有inser方式
set<int>s2(s1);//拷贝构造
set<int>s3 = s2;//等号赋值
4.2 大小和交换
set容器不支持resize
s1.size();
s1.empty();
s1.swap(s2);
4.3 插入和删除
s1.clear();//清空容器
s1.insert(elem);//插入元素,会自动排序
s1.erase(s1.begin());//删除指定迭代器的元素(注意是排序过的)
s1.erase(elem);//删除和elem匹配的元素
set容器插入会返回插入结果,multiset不会
set<int> s;
pair<set<int>::iterator, bool> ret = s.insert(10);
会返回一个对组,对组ret.second里面保存了是否插入成功的bool值。
multiset则不会返回bool
4.4 查找和统计
s1.find(key);//查找key是否存在,返回该元素的迭代器,找不到则返回s1.end()
s1.count(key);//统计key的元素个数
4.5 pair对组的使用
如果想返回两个数据,可以返回对组
pair<type, type> p (value1, value2);
pair<type, type> p = make_pair(value1, value2);
pair<string, int>p("a", 10);
cout << p.first << p.second << endl;
4.6 改变set容器排序规则(利用仿函数)
class Person
{
public:
string m_name;
int m_age;
Person(string name, int age)
{
m_name = name;
m_age = age;
}
};
class myCompare//set的指定排序规则需要在其插入值之前进行操作
{
public:
bool operator()(Person p1, Person p2) const //重载括号
{
return p1.m_age > p2.m_age; //倒序
}
};
void test()
{
Person p1("卢本伟", 25);
Person p2("孙笑川", 35);
Person p3("塔菲", 30);
Person p4("嘉然", 18);
Person p5("范小勤", 16);
set<Person, myCompare>s1;
s1.insert(p1);
s1.insert(p2);
s1.insert(p3);
s1.insert(p4);
s1.insert(p5);
for (set<Person>::iterator it = s1.begin(); it != s1.end(); it++)
{
cout << (*it).m_name << " " << (*it).m_age << endl;
}
}
int main()
{
test();
return 0;
}
5 map和multimap容器(python里面的字典)
map中所有元素都是pair
pair中第一个元素为key,起索引作用,第二个元素为value
所有元素按照key自动升序排序
优点:可以快速根据key查找到对应元素。
map不能有重复的key,multimap可以。两者都可以有重复的value
5.1 构造和赋值
map<int, int>m1;//创建map容器
m1.insert(pair<int, int>(1,10));
map<int, int>m2(m1);//拷贝构造
5.2 大小和交换
map容器不支持resize
m1.size();
m1.empty();
m1.swap(m2);
5.3 插入和删除
m.clear();//清空
m.insert(pair<int, int>(1, 10));
m.insert(make_pair(2,20));
m[3] = 30;//在key为3的元素赋值30。不建议用这种,容易混淆
//[]不建议用来插入,但可以利用key访问value
map<int, int>::iterator it=m.begin();
m.erase(it);//删除指定迭代与阿奴
m.earse(it, it + i);//删除迭代器区间内元素
m.earse(key);//删除指定key的元素
5.4 查找和统计
map<int,int>::iterator pos = m.find(key);//返回迭代器,找不到则返回m.end()
m.find(count);