1)deque的使用
http://c.biancheng.net/cplus/ 学习网站
deque和vector都属于动态数组,不过deque比vector更加强大;
#include
#include
#include
using namespace std;
int main()
{
deque a;
a.push_back(3);
a.push_front(4);
a.push_back(3);
a.push_front(4);
a.insert(a.begin()+2,94); //双端队列可以使用insert成员函数进行数据插入操作;
// for(auto e : a){ cout<<e<< ’ '; } //for循环输出
// for(deque::iterator iter = a.begin(); iter != a.end(); ++iter) { cout <<*iter<< ’ '; } //迭代器输出
for(deque::iterator iter = a.begin(); iter != a.end(); ++iter) //用algorithm算法按下标输出
{
size_t nOffset = distance(a.begin(),iter);
cout<<“a[”<<nOffset<<"] = " <<*iter<<endl;
}
cout<<endl;
return 0;
}
2)list的使用
(1)list的insert插入三种方式
#include
#include
using namespace std;
void printContext(const list& arg)
{
for(auto e : arg) { cout<<e<<’ '; }cout<<endl;
}
int main()
{
list a; //a是一个双向链表
a.push_back(5);
a.push_front(54);
a.push_back(44);
a.insert(a.begin(), 53); //有三种方法,1)用迭代器指定位置
a.insert(a.end(),3,20); //2)在后端插入3个20;
list b{11,22,33,44}; //3)把一个list的数据添加到另一个list容器里面,三个参数,都是迭代器
a.insert(a.end(),b.begin(),b.end());
printContext(a);
return 0;
}
(2)list的erase函数使用方法
#include
#include
using namespace std;
void printContext(const list& arg)
{
cout<<“{ “;
for(auto e : arg) { cout<<e<<’ '; }
cout<<”}”<<endl;
}
int main()
{
list a{22,33,44}; //a是一个双向链表
a.push_front(2);
list::iterator iter;
iter = a.insert(a.begin(),4); //insert会返回一个迭代器;
printContext(a);
a.erase(++iter); //把2删除,方式1
printContext(a);
iter = a.begin(); //如果删除完后,迭代器必须从新赋值,否则会报段错误;
a.erase(iter++,–a.end()); //按迭代器删除一个区间
printContext(a);
return 0;
}
(3)list的翻转和排序
int main()
{
list a{28,33,57,64}; //a是一个双向链表
a.reverse(); //翻转
printContext(a);
a.sort(); //排序
printContext(a);
return 0;
}
3)stack的使用
stack和queue都没有迭代器;
#include
#include
#include
#include
using namespace std;
int main()
{
stack<int,deque> a; //a是一个堆栈,用deque(双端队列)做的,默认用deque做堆栈;
stack<int,vector> c;
stack<int,list> b;
//堆栈不像list,vector等容器,不是一个独立存在的容器(不是原始容器),必须用list,vector,deque等生成一个容器;
//所以,堆栈又叫自适应容器,也叫(容器适配器),实际上是一个适配器!!!
//堆栈共计有5种操作,分别是: empty,size,pop,top,push; //只能操作一端,不支持迭代器
a.push(30);
a.push(40);
a.push(50);
a.push(60);
cout<<a.top()<<endl; //查看数据,有返回
cout<<a.size()<<endl;
a.pop(); //弹出数据,无返回;
cout<<a.size()<<endl;
return 0;
}
4)queue队列的使用
#include
#include
#include
#include
using namespace std;
int main()
{
//用list deque可以做queue,不可以用vector
//queue也是自适应容器,也叫(容器适配器),queue有6种操作:size front back push empty pop
queue<int ,deque> a; //默认是deque
queue<int ,list> b;
queue<int ,vector> c;
a.push(20); //最先进入
a.push(30);
a.push(40);
a.push(50);
cout<<a.size()<<endl;
cout<<“队首数据”<<a.front()<<endl;
cout<<“队尾数据”<<a.back()<<endl;
a.pop(); //弹出20
cout<<endl;
cout<<a.size()<<endl;
cout<<“队首数据”<<a.front()<<endl;
cout<<“队尾数据”<<a.back()<<endl;
return 0;
}
5)优先级队列
#include
#include
#include
using namespace std;
int main()
{
priority_queue pq; //最大值优先级队列,最大值永远在前面,用于优先级进程
priority_queue<int,deque,greater> pq_small; //最小值优先级队列,最小值在前面,添加一个greater谓词
pq_small.push(34);
pq_small.push(21);
pq_small.push(67);
pq_small.push(10);
cout<<“size is :”<<pq_small.size()<<endl;
while (!pq_small.empty())
{
cout<<"读出数据: "<<pq_small.top()<<endl;
pq_small.pop();
}
return 0;
}
6)顺序容器
vector list deque
顺序容器适配器
stack queue priority_queue
//可以用迭代器充当桥梁,初始化不同容器的数据
直接用对象初始化是错误的,可以用对象的迭代器初始化
int main()
{
vector svec{“hello”,“book”,“apple”};
// list slist(svec); //错误
list slist(svec.begin(),svec.end()); //这样初始化可以
for(auto e : slist) { cout<<e<<’ '; }cout<<endl;
return 0;
}
vector::iterator iter1 = a.end(); //最后一个元素的下一个
int main()
{
//迭代器和迭代器范围
vector a{22,43,12,67,88};
vector::iterator iter = a.begin();
vector::iterator iter1 = iter + a.size() / 2; //只有vector和deque才可以这样做
cout<<"中间的数据是: "<<*iter1<<endl;
return 0;
}
https://stormzhou.blog.csdn.net/article/details/105876365?spm=1001.2014.3001.5502 //c++primer需要总结
//在一个迭代器区间查找一个值,如果有返回true,否则,false;
没一种容器都有自己的迭代器,但所有的迭代器的接口是一样的!!!
两个迭代器,明确了一个范围
#include
#include
using namespace std;
bool findValue(vector::iterator beg,vector::iterator end,int val)
{
vector::iterator iter = beg;
bool tmp;
while (iter != end)
{
if(*iter == val)
{
tmp = true;
break;
}
else
++iter;
}
if(beg != end)
return tmp;
else
return tmp;
}
int main()
{
vector a{22,66,32,21,90};
cout<<findValue(a.begin(),a.end(),21)<<endl;
return 0;
}
//返回迭代器的案例
#include
#include
using namespace std;
vector::iterator findValue(vector::iterator beg,vector::iterator end,int val)
{
vector::iterator iter = beg;
while (iter != end)
{
if(*iter == val)
{
break;
}
else
++iter;
}
return iter;
}
int main()
{
vector a{22,66,32,21,90};
auto e = findValue(a.begin(),a.end(),33);
cout<<*e<<endl;
return 0;
}
5月5日
//顺序容器的操作
1)容器定义的类型
int main()
{
vector a; //这三个容器,学会一个,其他的两个都一样
list b;
deque c;
//以下都是向量内部定义的类型,我们把他叫做向量容器定义的类型(其他的deque list都一样)
vector<int>::size_type a1;
vector<int>::iterator a2;
vector<int>::const_iterator a3;
vector<int>::reverse_iterator a4;
vector<int>::const_reverse_iterator a5;
vector<int>::difference_type a6;
//以下三个是泛型程序设计
// vector<int>::value_type a7;
// vector<int>::reference a8;
// vector<int>::const_reference a9;
return 0;
}
for(vector::size_type i = 0; i < a.size(); i++) //要用size_type,不要用int定义
//链表没有下标
//逆序迭代器
vector::reverse_iterator riter = a.rbegin(); //输出66
vector::reverse_iterator riter1 = a.rend(); //输出非法;也就是说end和rend直接取数据都是不正确的;
2)//顺序容器添加元素
//添加元素都是副本,相当于拷贝了一份,对原来的数组没有影响;
int main()
{
vector a{11,22,33,44,55,66};
a.push_back(21);
auto it = a.end();
it = it -2;
a.insert(it,76); //insert有三种方法
a.insert(it,3,90);
list lvec{43,53,63};
a.insert(it,lvec.begin(),lvec.end()); //把list的容器数据添加到vector中
for(auto e : a)
{
cout<<e<<’ ';
}
cout<<endl;
return 0;
}
3)//容器比较大小(只能同类型比较)
int main()
{
vector a{2,3,5,7,9};
vector b{1,4,6,8,10};
if(a > b) //两个容器元素逐一比较
{
cout<<“a big”<<endl;
}
else if(a < b) cout<<“b big”<<endl;
else cout<<“a = b”<<endl;
return 0;
}
4)容器的元素大小操作
resize操作的时候,可能会使迭代器失效,推而广之,要牢记迭代器失效的事件何时发生,并重新赋值;
a.size(),a.resize(),a.max_size(),a,empty();
int main()
{
std::vector a{1,2,3,4,5,6,7};
cout<<a.size()<<endl;
a.resize(10,5); //初始化时是7个元素,扩充到10个元素,并用5填充,输出 1 2 3 4 5 6 7 5 5 5
cout<<a.size()<<endl;
for(auto e : a)
{
cout<< e <<’ ';
}
cout<<endl;
return 0;
}
5)容器元素访问
at,front和back返回的是引用;
//对容器元素的操作,最好先判断容器是不是空的,如果是空的,操作front和back的成员函数,会段错误;
std::vector a{1,2,3,4,5,6,7};
vector::reference refa = a.front(); //注意使用vector::reference的容器类型
cout<<refa<<endl;
std::vector a{1,2,3,4,5,6,7};
try
{
cout<<a.at(40)<<endl; //at如果下标非法,会抛出异常
}
catch(const std::exception& e) //正常情况下不会执行这里
{
cout<<“error---------”<<endl;
std::cerr << e.what() << ‘\n’;
}
5)删除容器元素
erase§,erase(b,e),clear(),pop_back(),pop_front();
vector a{1,3,4,5,6,7,88};
// a.erase(a[5]); 这样不可以删除,必须是都按迭代器删除
a.erase(iter + 5); //删除7这个元素;
a.erase(iter+ 2,iter + 5); //注意,前包后不包括,所以7不会删除
// a.pop_front(); vector不可以使用,只使用于list和deque;
find(a.begin(),a.end(),3); //返回的是迭代器
int main() //find的用法
{
vector a{1,3,4,5,6,7,88};
vector::iterator iter = find(a.begin(),a.end(),30); //返回的是迭代器
if(iter != a.end())
{
cout<<“find element”<<endl;
a.erase(iter);
}
else
cout<<“no find”<<endl;
return 0;
}
erase删除一个迭代器区间
int main()
{
vector a{1,3,4,5,6,7,88};
vector::iterator iter1 = find(a.begin(),a.end(),3); //返回的是迭代器
vector::iterator iter2 = find(a.begin(),a.end(),7); //返回的是迭代器
if( iter1 != a.end() && iter2 != a.end() )
{
cout<<“find element”<<endl;
a.erase(iter1,iter2);
}
else
cout<<“no find”<<endl;
return 0;
}
//输出1 7 8
5)赋值与交换操作
assign的特殊用法:容器类型不同,但容器模板类型参数相同的可以进行assign;
int main()
{
deque a{1,3,4,5,6,7,88};
deque b;
b = a; //可以直接赋值,当然包括vector,list也可以
b.swap(a); //a和b容器元素交换
b.assign(a.begin() + 2,a.end());//可以是两个迭代器
for(auto e : b)
{
cout<<e<<’ ';
}
cout<<endl;
return 0;
}
int main()
{
vector a;
list b;
a.push_back(“hello”);
a.push_back(“one”);
a.push_back(“two”);
a.push_back(“three”);
b.assign(a.begin(),a.end()); //vector的容器赋值给list;
for(auto e : b)
{
cout<<e<<’ ';
}
cout<<endl;
return 0;
}
6)vector容器的自增长 reserve保留
vector底层用是数组做的;
int main()
{
vector a;
a.resize(100,4);
a.reserve(500); //设置capacity的大小的,防着数据不断变化,造成数组的不断拷贝赋值
for(auto e : a)
{
cout<<e<<’ ';
}
cout<<endl;
cout<<a.size()<<endl;
cout<<a.capacity()<<endl; //输出是500
return 0;
}
7)容器的选用
vector:
优点:向量排序的时候非常快,排序完成后,进行二分查找非常快;
缺点:插入和删除元素非常慢;
list:
优点:插入和删除元素非常快;
deque :
两端都可以操作
8)string构造函数
int main()
{
string a1; //方式1
string a2(“hello”); //方式二
string a3(a2); //方式三
string a4(5,‘m’); //方式4
string a5(a4.begin(),a4.end()); //方式5
string tmpstr = “employee”;
string a6(tmpstr,3); //方式6; 从第三个元素开始,a6输出loyee
cout<<a6<<endl;
string a7(a2,0,2); //方式7,从0开始,要2个; a7输出he
cout<<a7<<endl;
return 0;
}
9)修改string对象的方法
插入insert,赋值assign,删除erase操作;
//用迭代器和下标进行数据插入
string::iterator it = a.begin();
a.insert(3,1,‘5’); //在下标为3位置,插入一个字符’5’
b.assign(a); //字符串赋值操作
int main()
{
string a(“hello world”);
a.erase(0,1).insert(0,“A”); //输出Aello world
cout<<a<<endl;
return 0;
}
10)只适合string类型的操作
substr,append,replace
//在做替换的时候,先删除,和插入;
int main()
{
string a(“helloworldAAA”);
string s = a.substr(5); //只有一个数字5表示从下标为5开始一直到结尾 worldAAA
string s2 = a.substr(4,3); //从下标4开始,取三个数据,输出owo
a.append(“666”); //等价于a.insert(a.size(),“666”);
a.replace(2,3,“rrr”); //从第二个位置下标开始,替换3个rrr,输出是herrrworldAAA
cout<<s2<<endl;
return 0;
}
11)字符串的查找
string 有六个查找相关的成员函数
find rfind(精确查找)
find_first_of find_last_of find_first_not_of find_last_not of