动态数据,可以随机访问。末尾添加和删除的效率高。元素的顺序和推入的顺序一致。
迭代器方式
void printV(vector<int>& v) {
for (vector<int>::iterator it = v.begin(); it != v.end(); it++) {
cout << *it << " ";
}
cout << endl;
}
vector<int>::iterator it = v.begin();
v.erase(v.begin(), v.end() - 1);
void test() {
vector<Student> v;
Student stu1(1, "first");
Student stu2(2, "second");
Student stu3(3, "third");
v.push_back(stu1);
cout << "------------" << endl;
v.push_back(stu2);
cout << "------------" << endl;
vector<Student>::iterator it = v.begin();
v.insert(it, stu3);
cout << "------------" << endl;
printStud(v);
}
运行结果:
insert.png
vector封装数组,list封装了链表,map和set封装了二叉树等。set关联式容器。set作为一个容器也是用来存储同一数据类型的数据类型,并且能从一个数据集合中取出数据,在set中每个元素的值都唯一,而且系统能根据元素的值自动进行排序。应该注意的是set中数元素的值不能直接被改变。C++ STL中标准关联容器set, multiset, map, multimap内部采用的就是一种非常高效的平衡检索二叉树:红黑树,也成为RB树(Red-Black Tree)。RB树的统计性能要好于一般平衡二叉树,所以被STL选择作为了关联容器的内部结构。set插入是按照一定规则排序,默认是由小到大。
pair<set<int>::iterator,bool>
bool标志着插入是否成功,而iterator代表插入的元素的定位器。
pair<set<int>::iterator, bool> p2=s.insert(7); if (p2.second) { cout <<"insert success"<< *p2.first << endl; }
#include "iostream"
using namespace std;
#include "set"
#include "vector"
//迭代器遍历
void print(set<int>& s) {
for (set<int>::iterator it = s.begin(); it != s.end(); it++) {
cout << *it <<" ";
}
cout << endl;
}
int main()
{
cout << "---------插入----------" << endl;
set<int> s;
s.insert(3);
set<int>::iterator it1 = s.begin();
cout << *it1 << endl;
s.insert(1);
//虽然插入1后,1在3的前面。但是it1指向的元素的内存。而set内所有的元素以节点
//方式存储,节点结构合链表差不多,插入和删除元素不需要做内存的移动,只需节点做
//变换即可
//牢记这个原则:不要使用过期的iterator。
cout << *it1 << endl;
s.insert(2);
s.insert(5);
s.insert(6);
print(s);
cout << "---------equal_range----------" << endl;
pair<set<int>::iterator, set<int>::iterator> p1=s.equal_range(4);
if (p1.first != s.end()) {
cout <<">=4 is "<< *p1.first << endl;
}
if (p1.second != s.end()) {
cout << ">4 is " << *p1.second << endl;
}
set<int>::iterator it = s.begin();
//不可以随机访问,关联型数据结构。红黑二叉树
//it=it+4;
cout << "---------erase----------" << endl;
s.erase(it);
print(s);
cout << "---------insert及其返回值----------" << endl;
pair<set<int>::iterator, bool> p2=s.insert(7);
if (p2.second) {
cout <<"insert success"<< *p2.first << endl;
}
print(s);
cout << "---------lower_bound、upper_bound----------" << endl;
//lower_bound是>=值的最小指针 upper_bound是>值的最小指针
cout << *s.lower_bound(5) << " " << *s.upper_bound(5) << endl;
return 0;
}
结果:
set_test1.png
#include "string"
#include "iostream"
#include "set"
using namespace std;
class Student {
private:
string name;
int number;
public:
Student(int number, string name) {
cout << "构造" << number << endl;
this->number = number;
this->name = name;
}
Student(const Student& student) {
this->number = student.getNumber();
this->name = student.getName();
}
void print()const {
cout << this->number << " "<<this->name << endl;
}
string getName()const {
return this->name;
}
int getNumber()const {
return this->number;
}
};
//函数对象
struct StuCmp{
bool operator()(const Student &first,const Student& second) {
return first.getNumber() > second.getNumber();
}
};
//遍历
void print(set<Student, StuCmp>& s) {
for (set<Student, StuCmp>::iterator it = s.begin(); it != s.end(); it++) {
it->print();
}
}
int main()
{
set<Student, StuCmp> set;
Student stu1(3, "third");
Student stu2(1, "first");
Student stu3(2, "second");
set.insert(stu1);
set.insert(stu2);
set.insert(stu3);
print(set);
return 0;
}
结果:
set_test2.png
set集合中一个值只能出现一次,而multiset集合中一个值可以出现多次。
什么时候需要用multiset?当然是需要用set,但是又允许重复key存在的时候了。什么时候用set?我的答案是:需要随时往容器中插入元素,随时对元素进行快速查找,又需要按某种顺序对元素进行遍历的时候
int main() {
multiset<Student, StuCmp> s;
Student stu1(3, "third");
Student stu2(1, "first");
Student stu3(2, "second");
Student stu4(2, "second_2");
s.insert(stu1);
s.insert(stu2);
multiset<Student,StuCmp>::iterator res= s.insert(stu3);
cout << "--------插入结果---------" << endl;
res->print();
res= s.insert(stu4);
cout << "--------插入结果---------" << endl;
res->print();
cout << "--------遍历---------" << endl;
print(s);
Student stu5(2, "second_3");
cout << "--------count方法---------" << endl;
cout << "count(5)=" << s.count(stu5) << endl;;
return 0;
}
这里的Student和StuCmp沿用Set中的定义。编译后发现出错:
multi_set_error.png
发现是StuCmp的问题,函数的const修饰符漏了。修改后
struct StuCmp{
bool operator()(const Student &first,const Student& second) const{
return first.getNumber() > second.getNumber();
}
};
运行结果:
multi_set_test3.png
list是一个线性双向链表结构,它的数据由若干个节点构成,每一个节点都包括一个信息块(即实际存储的数据)、一个前驱指针和一个后驱指针。它无需分配指定的内存大小且可以任意伸缩,这是因为它存储在非连续的内存空间中,并且由指针将有序的元素链接起来。由于其结构的原因,list 随机检索的性能非常的不好,因为它不像vector 那样直接找到元素的地址,而是要从头一个一个的顺序查找,这样目标元素越靠后,它的检索时间就越长。检索时间与目标元素的位置成正比。虽然随机检索的速度不够快,但是它可以迅速地在任何节点进行插入和删除操作。因为list 的每个节点保存着它在链表中的位置,插入或删除一个元素仅对最多三个元素有所影响,不像vector 会对操作点之后的所有元素的存储地址都有所影响,这一点是vector 不可比拟的。
void print(list<Student> l) {
for (list<Student>::iterator it = l.begin(); it != l.end(); it++) {
it->print();
}
}
struct PrintStu{
bool operator()(const Student& stu)const {
stu.print();
return true;
}
};
int main()
{
list<Student> l;
Student stu1(1, "first");
Student stu2(2, "second");
Student stu3(3, "third");
Student stu4(4, "fourth");
l.push_back(stu1);
l.push_front(stu2);
l.push_back(stu3);
l.push_front(stu4);
print(l);
cout << "---pop_back、pop_front-------" << endl;
Student s=l.back();
s.print();
l.pop_back();
s = l.front();
s.print();
l.pop_front();
cout << "----for_each------" << endl;
for_each(l.begin(), l.end(), PrintStu());
return 0;
}
结果:
list.png
这里使用了for_each函数算法。需要引入#include<algorithm>
头文件