vector,为动态空间,原迭代器在扩容后会失效
deque的迭代器很复杂,所以用的少
list,迭代器不会因为插入和删除操作而失效
set,map的迭代器为只读迭代器,不会失效,不能通过迭代器修改数据
一般遍历:
vector 可以用下标遍历
void print(int x)
{
cout<<x<<endl;
}
int main()
{
vector<int> a;
a.push_back(1);
a.push_back(3);
a.push_back(3);
vector<int>::iterator itstart=a.begin();
vector<int>::iterator itend=a.end();
// for(;itstart!=itend;itstart++)
// cout<<*itstart<
for_each(it_start,it_end,print);
return 0;
}
自定义类遍历:
class Person
{
public :
Person(int age)
{
this->age=age;
}
int age;
};
void print(Person &a)
{
cout<<a.age<<endl;
}
void test()
{
Person p1(1);
Person p2(4);
Person p3(11);
Person p4(13);
vector<Person> v;
v.push_back(p1);
v.push_back(p2);
v.push_back(p3);
v.push_back(p4);
vector<Person>::iterator itstart=v.begin();
vector<Person>::iterator itend=v.end();
for(;itstart!=itend;itstart++)
{
print(*itstart);
}
}
int main()
{
test();
return 0;
}
迭代器指向为容器
test2()
{
vector <int> v1;
vector<int> v2;
vector<vector<int> > vsum;
v1.push_back(1);v1.push_back(4);
v2.push_back(3);v2.push_back(12);
vsum.push_back(v1);vsum.push_back(v2);
vector<vector<int> >::iterator itstart=vsum.begin();
for(;itstart!=vsum.end();itstart++)
{
for(vector<int>::iterator it=(*itstart).begin();it!=(*itstart).end();it++)
{
cout<<*it<<" ";
}
cout<<endl;
}
}
int main()
{
// test();
test2();
return 0;
}
find()从左往右找
rfind()从右往左找
找到返回对应下标
找不到返回一个很大的数
resize(int num) 重新指定容器长度但是容量不变,变短,保留前num个,变长,默认为0
resize(int num,int x) 与上一样,变长,默认为x
二分查找返回下标迭代器:可以用在vector,普通数组,set,map
利用二分查找的方法在一个排好序的数组中进行查找的。(如果没有排好序,也是从头往后找的结果)
lower_bound( begin,end,num):从数组的begin位置到end-1位置二分查找第一个大于或等于num的数字,找到返回该数字的地址,不存在则返回end。通过返回的地址减去起始地址begin,得到找到数字在数组中的下标。
upper_bound( begin,end,num):从数组的begin位置到end-1位置二分查找第一个大于num的数字,找到返回该数字的地址,不存在则返回end。通过返回的地址减去起始地址begin,得到找到数字在数组中的下标。
在从大到小的排序数组中,重载lower_bound()和upper_bound()
lower_bound( begin,end,num,greater< type >() ):从数组的begin位置到end-1位置二分查找第一个小于或等于num的数字,找到返回该数字的地址,不存在则返回end。通过返回的地址减去起始地址begin,得到找到数字在数组中的下标。
upper_bound( begin,end,num,greater< type >() ):从数组的begin位置到end-1位置二分查找第一个小于num的数字,找到返回该数字的地址,不存在则返回end。通过返回的地址减去起始地址begin,得到找到数字在数组中的下标。
vector<int> v;
v.push_back(1231);
v.push_back(124242352);
v.push_back(123);
sort(v.begin(),v.end());
int idx=lower_bound(v.begin(),v.end(),1231)-v.begin();
if(v[idx]==123) cout<<"havs";
int num[6]={1,2,4,2,15,34};
sort(num,num+6);
int idx=lower_bound(num,num+6,4)-num;
if(num[idx]==4) cout<<"has";
#include
using namespace std;
const int maxn=100000+10;
const int INF=2*int(1e9)+10;
#define LL long long
int cmd(int a,int b){
return a>b;
}
int main(){
int num[6]={1,2,4,7,15,34};
sort(num,num+6); //按从小到大排序
int pos1=lower_bound(num,num+6,7)-num; //返回数组中第一个大于或等于被查数的值
int pos2=upper_bound(num,num+6,7)-num; //返回数组中第一个大于被查数的值
cout<<pos1<<" "<<num[pos1]<<endl;
cout<<pos2<<" "<<num[pos2]<<endl;
sort(num,num+6,cmd); //按从大到小排序
int pos3=lower_bound(num,num+6,7,greater<int>())-num; //返回数组中第一个小于或等于被查数的值
int pos4=upper_bound(num,num+6,7,greater<int>())-num; //返回数组中第一个小于被查数的值
cout<<pos3<<" "<<num[pos3]<<endl;
cout<<pos4<<" "<<num[pos4]<<endl;
return 0;
}
一、List定义:
List是stl实现的双向链表,与向量(vectors)相比, 它允许快速的插入和删除,但是随机访问却比较慢。使用时需要添加头文件
#include
二、List定义和初始化:
list<int>lst1; //创建空list
list<int> lst2(5); //创建含有5个元素的list
list<int>lst3(3,2); //创建含有3个元素的list
list<int>lst4(lst2); //使用lst2初始化lst4
list<int>lst5(lst2.begin(),lst2.end()); //同lst4
三、List常用操作函数:
Lst1.pop_back() 删除最后一个元素
Lst1.pop_front() 删除第一个元素
Lst1.push_back() 在list的末尾添加一个元素
Lst1.push_front() 在list的头部添加一个元素
Lst1.back() 返回最后一个元素
Lst1.begin() 返回指向第一个元素的迭代器
Lst1.clear() 删除所有元素
Lst1.end() 返回末尾的迭代器
Lst1.assign() 给list赋值
Lst1.erase() 删除一个元素 迭代器
Lst1.front() 返回第一个元素
Lst1.remove() 从list删除元素
Lst1.empty() 如果list是空的则返回true
Lst1.get_allocator() 返回list的配置器
Lst1.insert() 插入一个元素到list中
Lst1.max_size() 返回list能容纳的最大元素数量
Lst1.merge() 合并两个list
Lst1.rbegin() 返回指向第一个元素的逆向迭代器
Lst1.remove_if() 按指定条件删除元素
Lst1.rend() 指向list末尾的逆向迭代器
Lst1.resize() 改变list的大小
Lst1.reverse() 把list的元素倒转
Lst1.size() 返回list中的元素个数
Lst1.sort() 给list排序
Lst1.splice() 合并两个list
Lst1.swap() 交换两个list
Lst1.unique() 删除list中重复的元素
四、List使用示例:
示例1:遍历List
//迭代器法
for(list::const_iteratoriter = lst1.begin();iter != lst1.end();iter++) 示例2: #include typedef list LISTINT; void main() } #include using namespace std; //从前向后显示list队列的全部元素 } //测试list容器的功能 } vector只有尾插,尾删,为单向开口的连续内存空间。 d.assign(n,x) 赋值n个x 优先队列的用法 Container 必须是用数组实现的容器,比如 vector, deque 但不能用 list.STL里面默认用的是 vector. 比较方式默认用 operator< , 所以如果你把后面俩个参数缺省的话,优先队列就是大顶堆,队头元素最大。 对于自定义类型,则必须自己重载 operator< 或者自己写仿函数 自定义类型重载 operator< 后,声明对象时就可以只带一个模板参数。 重载函数operator< 也可以放到Node结构体申明里,但要加friend修饰 //以上代码实现的是一个小顶堆 会打印出两遍0-9. 默认为从小到大, 插入数据: 使用正向,反向迭代器遍历。或者用数组遍历。 复制容器(container)元素, 可以使用标准库(STL)的copy()和copy_n()函数. 如果要拷贝不同容器类型的时候我们要使用迭代器来进行容器内范围拷贝
{
cout<<*iter;
}
cout<
#include
#include
#include
#include
using namespace std;
typedef list LISTCHAR;
{
//用LISTINT创建一个list对象
LISTINT listOne;
//声明i为迭代器
LISTINT::iterator i;listOne.push_front(3);
listOne.push_front(2);
listOne.push_front(1);
listOne.push_back(4);
listOne.push_back(5);
listOne.push_back(6);
cout << "listOne.begin()--- listOne.end():" << endl;
for (i = listOne.begin(); i != listOne.end(); ++i)
cout << *i << " ";
cout << endl;
LISTINT::reverse_iterator ir;
cout << "listOne.rbegin()---listOne.rend():" << endl;
for (ir = listOne.rbegin(); ir != listOne.rend(); ir++) {
cout << *ir << " ";
}
cout << endl;
int result = accumulate(listOne.begin(), listOne.end(), 0);
cout << "Sum=" << result << endl;
cout << "------------------" << endl;
//用LISTCHAR创建一个list对象
LISTCHAR listTwo;
//声明i为迭代器
LISTCHAR::iterator j;
listTwo.push_front('C');
listTwo.push_front('B');
listTwo.push_front('A');
listTwo.push_back('D');
listTwo.push_back('E');
listTwo.push_back('F');
cout << "listTwo.begin()---listTwo.end():" << endl;
for (j = listTwo.begin(); j != listTwo.end(); ++j)
cout << char(*j) << " ";
cout << endl;
j = max_element(listTwo.begin(), listTwo.end());
cout << "The maximum element in listTwo is: " << char(*j) << endl;
Sleep(10000);
#include
#include
typedef list INTLIST;
void put_list(INTLIST list, char *name)
{
INTLIST::iterator plist;cout << "The contents of " << name << " : ";
for (plist = list.begin(); plist != list.end(); plist++)
cout << *plist << " ";
cout << endl;
void main(void)
{
//list1对象初始为空
INTLIST list1;
INTLIST list2(5, 1);
INTLIST list3(list2.begin(), --list2.end());//声明一个名为i的双向迭代器
INTLIST::iterator i;
put_list(list1, "list1");
put_list(list2, "list2");
put_list(list3, "list3");
list1.push_back(7);
list1.push_back(8);
cout << "list1.push_back(7) and list1.push_back(8):" << endl;
put_list(list1, "list1");
list1.push_front(6);
list1.push_front(5);
cout << "list1.push_front(6) and list1.push_front(5):" << endl;
put_list(list1, "list1");
list1.insert(++list1.begin(), 3, 9);
cout << "list1.insert(list1.begin()+1,3,9):" << endl;
put_list(list1, "list1");
//测试引用类函数
cout << "list1.front()=" << list1.front() << endl;
cout << "list1.back()=" << list1.back() << endl;
list1.pop_front();
list1.pop_back();
cout << "list1.pop_front() and list1.pop_back():" << endl;
put_list(list1, "list1");
list1.erase(++list1.begin());
cout << "list1.erase(++list1.begin()):" << endl;
put_list(list1, "list1");
list2.assign(8, 1);
cout << "list2.assign(8,1):" << endl;
put_list(list2, "list2");
cout << "list1.max_size(): " << list1.max_size() << endl;
cout << "list1.size(): " << list1.size() << endl;
cout << "list1.empty(): " << list1.empty() << endl;
put_list(list1, "list1");
put_list(list3, "list3");
cout << "list1>list3: " << (list1 > list3) << endl;
cout << "list1
deque容器
deque则是双向开口的连续线性空间
构造函数:
赋值操作:
大小操作:
双端操作:
取值:
stack容器
没有迭代器:
基本操作:
queue容器:
基本操作:
例子:
priority_queue 优先队列
priority_queue 对于基本类型的使用方法相对简单。他的模板声明带有三个参数: priority_queue
#include
#include
但此时不能像基本类型这样声明
priority_queue
原因是 greater 没有定义,如果想用这种方法定义 则可以按如下方式:#include
自实现优先队列#include
list容器:
迭代器:
list为双向循环链表的验证:
基本操作:
自定义类型排序:
set容器和multiset容器:
基本操作:
修改排序
set<int,greater<int> > a;//降序
set<int> a;//默认为升序,等同set
取数:
set<int>::iterator it;
// 用auto 也行
for(it=s.begin();it!=s.end();it++) //使用迭代器进行遍历
{
printf("%d\n",*it);
}
pair对组(也不算是容器)
pair<int,string> num_str[]={
{1000, "M"},
{900, "CM"},
{500, "D"},
};
for(auto [k,v]:num_str){
}
map/multimap容器
基本操作:
//map遍历按key从小到大
map<string,int>::iterator it=map.begin();
it->first it->second;
(*it).first (*it).second;
// unordered_map 遍历随机
unordered_map<int,string> mp;
mp[1] = "apple";
for(auto it=mp.begin();it!=mp.end();it++)
常用:正向:
for(auto it=m1.begin();it!=m1.end();it++){
printf(" %d %.1lf",it->x,it->y);
}
反向:
for(auto it=m1.end();it!=m1.begin();){
--it;
printf(" %d %.1lf",it->x,it->y);
}
int main(){
map<int,string> mapStudent;
mapStudent[1] = "student_one";
mapStudent[2] = "student_two";
mapStudent[3] = "student_three";
map<int, string>::reverse_iterator iter;
for(iter = mapStudent.rbegin(); iter != mapStudent.rend(); iter++){
cout<<iter->first<<" "<<iter->second<<endl;
}
return 0;
}
二维容器:
1,常用
vector<int> a[1000];
a[1].push_back(1);
2,非常用
vector<vector<int> > v;
//要使用指定位置存值,就要先resize ,但是用了哪一层用了resize ,那一层就不能用push_back
//第一层,第二层都使用resize,就不能使用push_back() 放不进去的
v.resize(100);
v[1].resize(100);
v[1][1]=2;//不能使用push_back() 放不进去的
// 第一层使用resize,第二层不使用,可以用push_back()存值
v[1].push_back(1);
v[1].push_back(2);
v[1].push_back(3);
v[1].push_back(4);
cout<<v[1][1];
容器的复制拷贝:
在我们要初始化一个容器为另一个容器的拷贝时,如果不适用迭代器,直接使用容器变量名进行拷贝只能拷贝相同容器类型的#include
using namespace std;
int main()
{
list<int> l = {1, 2, 3};
list<int> v(l);
//vector
#include
using namespace std;
int main()
{
list<int> l = {1, 2, 3};
vector<int> v(l.begin(), l.end());
for(auto i : v)
{
cout << i << endl;
}
return 0;
}
STL容器使用时机:
函数对象
class Compare
{
public:
bool operator()(int a,int b)
{
return a>b;
}
};
void test11()
{
vector<int> a;
a.push_back(1);
a.push_back(12);
a.push_back(3);
sort(a.begin(),a.end(),Compare());
for(int i=0;i<a.size();i++)
{
cout<<a[i]<<endl;
}
}
谓词:
bool greater2(int a)
{
return a>2;
}
void test11()
{
vector<int> a;
a.push_back(1);
a.push_back(12);
a.push_back(3);
//find_if()返回一个迭代器
vector<int>::iterator it=find_if(a.begin(),a.end(),greater2);
if(it!=a.end())
{
cout<<*it<<endl;
}
}
int main()
{
test11();
return 0;
}
内建函数对象
函数对象适配器
完整例题:
L2-005 集合相似度
int n;
set<int> u[60];
void fun(int a,int b)
{
int scnt=0;
set<int>::iterator it;
for(it=u[a].begin();it!=u[a].end();it++)
{
if(u[b].find(*it)!=u[b].end()) scnt++;
}
int sum=u[a].size()+u[b].size()-scnt;
printf("%.2f%%\n",scnt*1.0/sum*100);
}
int main()
{
cin>>n;
int k;
for(int i=0;i<n;i++)
{
cin>>k;
for(int j=0;j<k;j++)
{
int a;
cin>>a;
u[i+1].insert(a);
}
}
int m;
cin>>m;
while(m--)
{
int s;int ss;
cin>>s>>ss;
fun(s,ss);
}
return 0;
}
L2-015
#include
L2-015:
#include