19、线性容器、适配器容器
- 线性容器
- 向量 vector
- 初始化
- 迭代器使用
- 双端队列 deque
- 双端队列和向量的差别
- 成员函数
- 列表 list
- 常用函数
- 适配器容器
- 栈
- 队列
线性容器
向量 vector
成员函数
front() 获取首元素
back() 获取尾元素
insert() 插入元素
erase() 删除元素
push_back() 添加尾元素
pop_back() 删除尾元素
empty() 判空
clear() 清空
size() 向量维护的元素个数
resize() 设置向量元素个数获取向量容量
capacity() 获取向量容器
reserve() 设置向量的容量
初始化
向量中的元素被存储在一段连续的内存空间中
vector<int> values{3,10,2,66,18,22,5,7,11};values.reserve(15);
- 向量维护的内存空间会随着新元素的增加而自动增长
- 内存空间的连续性不会妨碍向量元素的增加,如果内存空间无法满足新元素的增加,向量会开辟新的足够的连续内存空间,并把原内存空间的数据复制到新的内存空间,释放原内存空间.
- 向量的增加会伴随着内存空间的分配和释放,元素复制和销毁等额外开销。
- 如果能够在创建向量时,合理预分配一些空间将很大程度上缓解这些额外开销。
// 向量
#include <iostream>
#include <vector>
#include <cstdio>
using namespace std;
class Student{
public:
Student(const string& name = ""):m_name(name){
cout << "缺省构造了" << m_name << "(" << this << ")" << endl;
}
Student(const Student& that):m_name(that.m_name){
cout << "用" << that.m_name << "(" << &that << ") 拷贝构造了" << m_name << "(" << this << ")" << endl;
}
~Student(){
cout << "析构了" << m_name << "(" << this << ")" << endl;
}
private:
string m_name; // 姓名
};
int main(){
vector<Student> vs;
vs.reserve(10);
vs.push_back(Student("张飞"));
vs.push_back(Student("赵云"));
vs.push_back(Student("关羽"));
getchar();
return 0;
}//
迭代器使用
// 向量
#include <iostream>
#include <vector>
#include <algorithm> // find/sort
using namespace std;
class Student{
public:
Student(const string& name = "",int age = 0):m_name(name),m_age(age){}
bool operator==(const Student& that)const{
return m_name == that.m_name && m_age == that.m_age;
}
bool operator<(const Student& that)const{
return m_age < that.m_age;
}
bool operator>(const Student& that)const{
return m_age > that.m_age;
}
private:
string m_name; // 姓名
int m_age; // 年龄
friend ostream& operator<<(ostream& os,const Student& stu);
};
ostream& operator<<(ostream& os,const Student& stu){
return os << stu.m_name << ":" << stu.m_age;
}
void print(const string& str,vector<Student>& v){
cout << str << endl;
typedef vector<Student>::iterator IT;
for(IT it = v.begin(); it != v.end();++it){
cout << *it << endl;
}
cout << "----------------------------" << endl;
}
int main(){
vector<Student> vs;
vs.reserve(4);
vs.push_back(Student("张飞",22));
vs.push_back(Student("赵云",25));
vs.push_back(Student("关羽",30));
vs.push_back(Student("马超",32));
vs.push_back(Student("黄忠",45));
print("添加元素后:",vs);
vs.insert(vs.begin(),Student("刘备",33)); // 增
print("在迭代器指向的位置插入元素后:",vs);
vs.erase(vs.begin()); // 删
print("删除迭代器指向的位置的元素后:",vs);
typedef vector<Student>::iterator IT;
IT it = vs.begin(); // 改
*it = Student("诸葛亮",32);
print("更改迭代器指向位置的元素后:",vs);
IT fit = find(vs.begin(),vs.end(),Student("赵云",25)); // 查
if(fit != vs.end()){
vs.erase(fit);
print("找到并删除后:",vs);
}else
cout << "没有找到" << endl;
sort(vs.begin(),vs.end(),greater<Student>());
print("排序后:",vs);
cout << "vs的容量:" << vs.capacity() << endl;
cout << "vs的大小:" << vs.size() << endl;
vs.resize(6);
print("resize之后:",vs);
return 0;
}//
双端队列 deque
双端队列和向量的差别
- 和向量差别就是首尾两端同样都是开放的,因此他同时提供了首尾两端增删元素的接口。
- 没有提供设置/获取容量的函数,设置和获取容器大小的函数存在
成员函数
front() 获取首元素
back() 获取尾元素
insert() 插入元素
erase() 删除元素
push_front() 添加首元素
pop_front() 删除首元素
push_back()添加尾元素
pop_back()删除尾元素
empty()判空
clear()清空
size()向量维护元素个数
resize()设置向量元素个数
// 双端队列
#include <iostream>
#include <deque>
#include <algorithm> // find/sort
using namespace std;
class Student{
public:
Student(const string& name = "",int age = 0):m_name(name),m_age(age){}
bool operator==(const Student& that)const{
return m_name == that.m_name && m_age == that.m_age;
}
bool operator<(const Student& that)const{
return m_age < that.m_age;
}
bool operator>(const Student& that)const{
return m_age > that.m_age;
}
private:
string m_name; // 姓名
int m_age; // 年龄
friend ostream& operator<<(ostream& os,const Student& stu);
};
ostream& operator<<(ostream& os,const Student& stu){
return os << stu.m_name << ":" << stu.m_age;
}
void print(const string& str,deque<Student>& v){
cout << str << endl;
/* typedef deque<Student>::iterator IT;
for(IT it = v.begin(); it != v.end();++it){
cout << *it << endl;
}*/
/*
for(const auto& s : v) // -std=c++11
cout << s << endl;*/
for(int i=0;i<v.size();i++)
cout << v[i] << endl;
cout << "----------------------------" << endl;
}
int main(){
deque<Student> vs;
vs.push_front(Student("张飞",22));
vs.push_front(Student("赵云",25));
vs.push_front(Student("关羽",30));
vs.push_back(Student("马超",32));
vs.push_back(Student("黄忠",45));
print("添加元素后:",vs);
vs.insert(vs.begin(),Student("刘备",33)); // 增
print("在迭代器指向的位置插入元素后:",vs);
vs.erase(vs.begin()); // 删
print("删除迭代器指向的位置的元素后:",vs);
typedef deque<Student>::iterator IT;
IT it = vs.begin(); // 改
*it = Student("诸葛亮",32);
print("更改迭代器指向位置的元素后:",vs);
IT fit = find(vs.begin(),vs.end(),Student("赵云",25)); // 查
if(fit != vs.end()){
vs.erase(fit);
print("找到并删除后:",vs);
}else
cout << "没有找到" << endl;
sort(vs.begin(),vs.end(),greater<Student>());
print("排序后:",vs);
cout << "vs的大小:" << vs.size() << endl;
vs.resize(6);
print("resize之后:",vs);
return 0;
}//
列表 list
常用函数
front()获取首元素
back()获取尾元素
insert()插入元素
erase()删除元素
push_front()添加首元素
pop_front()删除首元素
push_back()添加尾元素
pop_back()删除尾元素
empty()判空
clear()清空
size()向量维护元素个数
resize()设置向量元素个数
- 唯一化
void unique(void); 将连续重复出现的元素唯一化
- 排序 (都是全局排序) 注意sort是成员函数
void sort(void)通过 < 比大小
template<class LESS>void sort(LESS less) 通过比较器比大小
- 拆分: 将参数列表中的部分或全部元素剪切到调用列表中
template<class IT>void splice( IT pos, list& lst )
template<class IT>void splice( IT pos, list& lst, IT del )
template<class IT>void splice( IT pos, list& lst, IT begin, IT end )
// 列表
#include <iostream>
#include <list>
using namespace std;
void print(const string& str, list<int>& l){
cout << str << endl;
for( const auto& i : l)
cout << i << ' ';
cout << endl;
cout << "-------------------------------------------" << endl;
}
int main(){
list<int> ls;
for(int i=0; i<5;i++) // 14 13 12 11 10
ls.push_front(10+i);
for(int i=0;i<5;i++) // 14 13 12 11 10 10 11 12 23 14
ls.push_back(10+i);
print("添加首尾节点后:",ls);
// 唯一化
ls.unique();
print("唯一化后:",ls);
ls.remove(13);
print("删除所有的13后:",ls);
ls.sort(); // 排序
print("升序排序后:",ls);
ls.sort(greater<int>());
print("降序排序后:",ls);
list<int> lst{1000,2000,300,4000,5000,6000};
// ls.splice(++ls.begin(),lst); // 将lst的所有元素剪切到ls的第二个位置
// ls.splice(++ls.begin(),lst,lst.begin()); // 将lst的第一个元素剪切到ls的第二个位置
ls.splice(++ls.begin(),lst,++lst.begin(),--lst.end()); // 将lst的第二个元素 到 倒数第二个元素 剪切到ls的第二个位置
print("ls :",ls);
print("lst:",lst);
return 0;
}
适配器容器
栈
// 栈
#include <iostream>
#include <stack>
#include <vector>
//#include <deque>
#include <list>
using namespace std;
int main(){
// stack<int> s;
// stack<int,vector<int> > s;
// stack<int,list<int> > s;
stack<int,deque<int> > s;
s.push(1);
s.push(2);
s.push(3);
s.push(4);
s.push(5);
s.push(6);
while(!s.empty()){
cout << s.top() << endl; // 获取栈顶元素
s.pop(); // 弹栈(删除栈顶元素)
}
return 0;
}
队列
// 队列
#include <iostream>
#include <queue>
#include <vector>
//#include <deque>
#include <list>
using namespace std;
int main(){
// queue<int> s;
// queue<int,vector<int> > s; // error:向量不能做为队列的底层容器 没有pop_front
// queue<int,list<int> > s;
queue<int,deque<int> > s;
s.push(1);
s.push(2);
s.push(3);
s.push(4);
s.push(5);
s.push(6);
while(!s.empty()){
cout << s.front() << endl; // 获取队首元素
s.pop(); // 出队(删除队首元素)
}
return 0;
}