C++ STL组件
STL提供三种类型的组件:容器,迭代器和算法。
1. 容器有两类,分为顺序容器,关联容器。顺序容器:Vector,list,dequeue,string等;关联容器:set,multiset,map,multimap
2. 迭代器的作用是遍历容器。
3. STL算法库包含四类算法:排序,不可变序算法,变序性算法 和数值算法。
1. vector向量容器装10个整数,使用迭代器iterator和accumulate统计这10个元素的和。
1. vector向量容器
vector可以向数组一样对元素进行随机访问,可以在尾部插入元素。
vector容器下标从0开始计数,vector的大小是n,元素下标是 0 ~ n-1. 使用push_back()方法从尾部扩张,使用insert()在某个位置插入新
元素。
begin() 和 end()分别返回首元素位置的迭代器 和 最后一个元素的下一个元素位置的迭代器。
注:end()返回的并不是最后一个元素的迭代器,而是最后一个元素的后面一个元素的迭代器。
创建vector对象:
vector<int> v;
不指定大小 vector<double> v(10); 指定容器的大小为10 vector<double> v(10, 8.6); 指定大小与初始值(8.6)
尾部扩张:
使用push_back()对vector容器在尾部追加新元素。
#include <iostream>
#include <vector>
using namespace std;
int main()
{
vector<int> v;
v.push_back( 2);
v.push_back( 5);
v.push_back( 7);
return 0;
}
下标方式访问vector元素:
vector<int> v1(3);
v1[0] = 2;
v1[1] = 5;
v1[2] = 7;
迭代器访问vector元素:
vector<int>::iterator it;
for( it = v.begin(); it!=v.end(); it++)
{
cout<<*it << endl;
}
cout<<endl;
元素插入:
v.insert(v.begin(), 8);
// 在开始的位置插入数据
v.insert(v.begin() + 2, 1);
// 在开始向后的两个元素位置处插入数据
v.insert(v.end(), 3);
// 在最后一个元素后面插入数据
元素删除:
for( i = 0; i < 10; i ++)
{
v.push_back(i);
}
for( it = v.begin(); it!=v.end(); it++)
{
cout<<*it << " ";
}
cout<<endl;
v.erase(v.begin() + 2);
// 删除第三个元素
for( it = v.begin(); it!=v.end(); it++)
{
cout<<*it << " ";
}
cout<<endl;
v.erase(v.begin() + 1, v.begin() + 5);
// 删除第二个元素到第五个元素
for( it = v.begin(); it!=v.end(); it++)
{
cout<<*it << " ";
}
cout<<endl;
v.clear();
// 清楚所有的元素
cout<<v.size() << endl;
使用反向排列算法:
reverse()方向排序算法。加入#include<algorithm>头文件
for( i = 0; i < 10; i ++)
{
v.push_back(i);
}
for( it = v.begin(); it!=v.end(); it++)
{
cout<<*it << " ";
}
cout<<endl;
reverse(v.begin(), v.end());
for( it = v.begin(); it!=v.end(); it++)
{
cout<<*it << " ";
}
cout<<endl;
sort()算法对元素排序
默认情况下是对元素进行从小到大的升序排序
for( i = 0; i < 10; i++)
{
v.push_back(9 - i);
}
for( i = 0; i < 10; i++)
{
cout<<v[i] << " ";
}
cout<< endl;
sort(v.begin(), v.end());
for( i = 0; i < 10; i++)
{
cout<< v[i] << " ";
}
cout<< endl;
// 自己加入比较函数,进行从大到小的排序
比较函数如下:
bool Comp(const int &s1, const int s2)
{
return s1 > s2;
}
for( i = 0; i < 10; i++)
{
v.push_back(i);
}
for( i = 0; i < 10; i++)
{
cout<<v[i] << " ";
}
cout<< endl;
sort(v.begin(), v.end(), Comp);
// 在调用sort时,传入比较函数
for( i = 0; i < 10; i++)
{
cout<< v[i] << " ";
}
cout<< endl;
使用类的成员方法作为比较函数:
class myless
{
public:
bool operator()(const int &a, const int &b)
{
return a < b;
}
};
for( i = 0; i < 10; i++)
{
v.push_back( 9 - i);
}
for( i = 0; i < 10; i++)
{
cout<<v[i] << " ";
}
cout<< endl;
sort(v.begin(), v.end(), myless());
// 传入类的比较函数,此处是类的重载操作符
for( i = 0; i < 10; i++)
{
cout<< v[i] << " ";
}
cout<< endl;
对结构体变量进行排序,需要对结构体的比较做出对比函数:
定义结构体,用于排序,分别使用第一个关键字和第二个关键字:
typedef struct tag_Name
{
string first;
string last;
}NAME;
bool CompbyFirst(const NAME &n1, const NAME &n2)
{
return n1.first < n2.first;
}
bool CompbyLast(const NAME &n1, const NAME &n2)
{
return n1.last < n2.last;
}
vector<NAME> vName;
vector<NAME>::iterator j;
NAME tmp;
tmp.first = "liu";
tmp.last = "bei";
vName.push_back(tmp);
tmp.first = "zhao";
tmp.last = "yun";
vName.push_back(tmp);
tmp.first = "gun";
tmp.last = "yu";
vName.push_back(tmp);
tmp.first = "zhang";
tmp.last = "fei";
vName.push_back(tmp);
cout<<"by first:"<<endl;
sort(vName.begin(), vName.end(), CompbyFirst);
for(j=vName.begin(); j!= vName.end(); j++)
{
cout<<j->first<<" "<<j->last<<endl;
}
cout<<"by last:"<<endl;
sort(vName.begin(), vName.end(), CompbyLast);
for(j=vName.begin(); j!= vName.end(); j++)
{
cout<<j->first<<" "<<j->last<<endl;
}
向量的大小:
for( i = 0; i < 10; i++)
{
v.push_back( 9 - i);
}
cout<< v.size() <<endl;
// 输出向量中元素的个数
cout<< v.empty() <<endl;
// 判断是否为空,如果不为空则返回0,否则返回1
v.clear();
cout<< v.empty() <<endl;
2. string容器:
vector<char> 也可以用于处理字符串但是其功能比不上string,vector类似于C中的字符数组。
string用到的头文件为string
创建字符串,以及检查其长度:
#include <iostream>
#include <string>
using namespace std;
int main()
{
string s;
cout<< s.length() <<endl;
s = "hello, c++ STL";
// 静态字符串直接赋值给string
cout<<s << " s.length: " << s.length() <<endl;
char ss[500];
memset(ss, 0, sizeof(ss));
char ss[500];
memset(ss, 0, sizeof(ss));
scanf( "%s", &ss);
s = ss;
// 字符数组赋值给string
cout<<s<<endl;
return 0;
}
从字符串尾部追加字符与字符串:
s = s + 'a';
s = s + 'b';
s = s + 'c';
cout<<s << endl;
s = s + "123";
cout << s << endl;
s.append("xyz");
cout << s <<endl;
注:append的参数为 char* ,因此不能用于追加字符,例如'b'
向字符串中插入字符,注意字符从0开始计数:
s = "1234567";
string::iterator sit;
sit = s.begin();
s.insert( sit + 1, 'p');
cout << s << endl;
访问string 的元素:
cout << s[0] << endl;
cout << s[1] - 'a' << endl;
// string的每一个元素都是 char
清空字符串,则直接给它赋值空串,或者使用string的clear方法。
s.clear();
使用erase方法可以删除迭代器所指向的元素或者一个区间中所有元素。
s = "abc1234567";
sit = s.begin();
s.erase(sit + 3);
cout << s <<endl;
s.erase(sit + 1, sit + 4);
// 删除一个区间的元素
cout<< s <<endl;
替换string对象的字符:
s = "abc1234567";
s.replace(3, 3, "good");
// 下标3开始的三个连续字符替换为good
cout << s <<endl;
搜索string对象的元素或字串,find方法查找字符串中第一个字符元素或字串,找到返回下标值,否则返回4294967295:
s = "cat dog cat";
cout << "find \'c\': " << s.find('c') <<endl;
// 查找第一个字符 'c'
cout << "find \"c\": " << s.find("c") <<endl;
// 查找第一个字串 "c"
cout << "find \"cat\": " << s.find("cat") <<endl; //
cout << "find \"dog\": " << s.find("dog") <<endl; //
cout << "find \"dogc\": " << s.find("dogc") <<endl; // 查找dogc,找不到,返回上述值。
字符串比较,使用compare()方法,比对方大则返回1 小则返回-1 相等则是0:
s = "cat dog cat";
cout<< s.compare("cat") << endl;
// 大的时候,返回的是 剩余的字符个数
cout<< s.compare("cat ") << endl;
// 大的时候返回1,因为字符数量相等
cout<< s.compare("cat dog cat") << endl;
cout<< s.compare("dog") << endl;
反向字符串,用reverse方法:
reverse方法位于#include<algorithm>中。
s = "1234567abc";
cout<<s <<endl;
reverse(s.begin(), s.end());
cout<<s <<endl;
将string对象作为vector的元素,类似于字符串数组。
vector<string> vstr;
vstr.push_back("Jack");
vstr.push_back("Mike");
vstr.push_back("Tom");
cout<< vstr[0] <<endl;
cout<< vstr[2] <<endl;
cout<< vstr[0][1] <<endl;
cout<< vstr[1][1] <<endl;
string类型的数字化处理:
ACM中常常需要将读入的数组的每位分离出来,如果采取取余的方法花费的时间太长,这个时候可以将读入的数据当成字符串来处理
这样方便,省时,:
s = "1234059";
for( i = 0; i < s.length(); i++)
{
if(s[i]=='0') sum += 0;
else if(s[i]=='1') sum += 1;
else if(s[i]=='2') sum += 2;
else if(s[i]=='3') sum += 3;
else if(s[i]=='4') sum += 4;
else if(s[i]=='5') sum += 5;
else if(s[i]=='6') sum += 6;
else if(s[i]=='7') sum += 7;
else if(s[i]=='8') sum += 8;
else if(s[i]=='9') sum += 9;
}
cout<<sum<<endl;
string 对象与字符串数组的互操作:
char cstr[100];
scanf("%s", &cstr);
s = cstr;
printf( s.c_str());
cout<<endl;
printf(cstr);
cout<<endl;
cout<<s<<endl;
cout<<cstr<<endl;
string对象与scanf函数
string s1, s2, s3;
char sa[20], sb[20], sc[20];
sscanf("abc 123 pc", "%s %s %s", sa, sb, sc);
// 格式化字符串到字符数组
s1 = sa;
s2 = sb;
s3 = sc;
cout<< s1 << " " << s2 << " " << s3 << endl;
int a, b, c;
sscanf("1 2 3", "%d %d %d", &a, &b, &c);
// 格式化数字到数字变量
cout<<a << " " << b << " " << c << endl;
sscanf("4,5$6", "%d,%d$%d", &a, &b, &c);
// 格式化数字到数字变量
cout<<a << " " << b << " " << c << endl;
string对象与数值相互转换:
需要用到ostringstream 和 istringstream对象:
string convertToString(double x)
{
ostringstream o;
if (o << x)
return o.str();
return "conversion error";
}
double convertFromString(const string &s)
{
istringstream i(s);
double x;
if( i >> x)
return x;
return 0.0;
}
char bstr[10];
string astr;
sprintf(bstr, "%d", 1957);
// C的方法转换
astr = bstr;
cout<< astr <<endl;
string dstr = convertToString(1957);
// 使用C++ 的方法转换
cout << dstr <<endl;
string dd = "2006";
int p = convertFromString(dd) + 2;
// C++方法转换
cout << p <<endl;
3. set结合容器:
set集合实现了红黑树的平衡二叉检索树的数据结构,在插入元素时自动调整二叉树的排序。二叉树的高度最小,检索速度最快。
set不会重复插入相同键值的元素,而采取忽略处理。
平衡二叉检索树在插入元素时,会自动将元素按照键值由小到大的顺序排列。
set容器的键值不可以修改。如果把容器的一个键值修改了,set容器会根据新的键值旋转子树,以保持新的平衡。
这样修改的键值就不再原先的位置上了。构造set集合的主要目的是为了快速检索。
multiset,map,multimap的内部结构也是平衡二叉检索树。
使用set容器要包含 #include<set>
#include <iostream>
#include <set>
using namespace std;
int main()
{
set<int> s;
s.insert(8);
s.insert(1);
s.insert(12);
s.insert(6);
s.insert(8);
// 反复插入,不会进行插入操作
set<int>::iterator it;
for(it = s.begin(); it != s.end(); it++)
{
cout<< *it <<endl;
}
cout<<endl;
return 0;
}
输出结果是按照从小到大的顺序输出。也即插入过程中进行了排序。
set的反向遍历:
set<int>::reverse_iterator rit;
for(rit = s.rbegin(); rit != s.rend(); rit++)
{
cout<< *rit << " ";
}
cout<<endl;
反向遍历的迭代器,set<int>::reverse_iterator rit;
元素的删除:
删除元素后也会自动承诺哦更新调整内部的红黑树的平衡。
删除的对象可以是某个迭代器位置上的元素,等于某键值的元素,一个区间上的元素和清空集合。
s.erase(6);
// 删除键值为6的元素
for(rit = s.rbegin(); rit != s.rend(); rit++)
{
cout<< *rit << " ";
}
cout<<endl;
s.clear();
// 清空set
cout<<s.size() <<endl;
// set大小
元素的检索:
使用find方法对集合进行搜索,查找到键值,则返回键值的迭代器,否则返回end()的值。
it = s.find(6);
if(it != s.end())
cout<<*it << endl;
else
cout<< "not find it"<<endl;
it = s.find(20);
if(it != s.end())
cout<<*it << endl;
else
cout<< "not find it"<<endl;
自定义比较函数:
在使用insert()将元素插入到集合中去时,集合会根据设定的比较函数将改元素放到应该放置的节点上。如果没有
设定比较函数,则使用默认的函数,即从小到大的顺序插入元素。
比较函数的编写方法:
元素不是结构体,可以编写比较函数:
比较函数如下:
struct myComp
{
bool operator()(const int &a, const int &b)
{
if(a!=b)
return a > b;
else
return a > b;
}
};
set<int, myComp> s1;
s1.insert(8);
s1.insert(1);
s1.insert(12);
s1.insert(6);
s1.insert(8);
set<int, myComp>::iterator it1;
for(it1 = s1.begin(); it1 != s1.end(); it1++)
{
cout<<*it1<<" ";
}
cout<<endl;
结果按照从大到小的顺序排列。
元素为结构体,直接将比较函数写在结构体中。
结构体定义,以及结构体比较的函数:
struct Info
{
string name;
float score;
bool operator < (const Info &a) const
{
return a.score < score;
}
};
set<Info> sstrct;
Info info;
info.name = "Jack";
info.score = 80.5;
sstrct.insert(info);
info.name = "Tomi";
info.score = 20.5;
sstrct.insert(info);
info.name = "Nacy";
info.score = 60.5;
sstrct.insert(info);
set<Info>::iterator itstrct;
for( itstrct = sstrct.begin(); itstrct != sstrct.end(); itstrct++)
{
cout<<(* itstrct).name << " : " << (*itstrct).score <<endl;
}
cout<<endl;
4. multiset 多重集合容器
multiset与set一样,使用红黑树组织元素数据,不同的是multiset允许重复的元素键值插入。
由于multiset包含重复元素,因此在插入删除和查找元素上有区别。
包含multiset的头文件也为 #include<set>
#include <iostream>
#include <set>
#include <string>
using namespace std;
int main()
{
multiset<string> ms;
ms.insert("abc");
ms.insert("123");
ms.insert("111");
ms.insert("aaa");
ms.insert("123");
multiset<string>::iterator it;
for( it = ms.begin(); it != ms.end(); it ++)
{
cout<< *it<<endl;
}
cout<<endl;
return 0;
}
multiset元素的删除:
使用erase方法可以删除multiset独享中某个迭代器位置的元素,区间上的元素,以及键值为某个值的所有重复元素。
int n = ms.erase("123");
// 将所有等于该值的元素都删除
cout<<"Tatol deleted: "<<n <<endl;
for( it = ms.begin(); it != ms.end(); it ++)
{
cout<< *it<<endl;
}
cout<<endl;
查找元素:
使用find方法查找元素,如果找到则返回元素迭代器的位置,如果是重复元素,则返回第一个重复元素的迭代器位置。
如果没有找到返回end()值。
it = ms.find("123");
if(it != ms.end())
{
cout<<*it<<endl;
}
else
{
cout<<"Not find!"<<endl;
}
it = ms.find("bbb");
if(it != ms.end())
{
cout<<*it<<endl;
}
else
{
cout<<"Not find!"<<endl;
}
5. map映照容器
map容器的元素数据由一个键和一个值组成。键与值之间一一对应。
map也采用的是红黑树实现,插入的元素键值不允许重复。比较函数只对元素的键进行比较,元素的值可以通过键来检索。
其包含在 #include<map>中
#include <iostream>
#include <map>
#include <string>
using namespace std;
int main()
{
map<string, float> m;
m["Jack"] = 98.5;
m["Tomi"] = 97.0;
m["Kate"] = 96.3;
map<string, float>::iterator it;
for(it = m.begin(); it != m.end(); it++)
{
cout<< (*it).first << " : " << (*it).second <<endl;
}
cout<< endl;
return 0;
}
删除元素:
与set一样,map的erase()删除元素的函数,可以删除某个迭代器位置上的元素,等于某个键值的元素,一个区间上的所有元素。
也可以使用clear将所有的元素删除。
map<int, char> m1;
m1[25] = 'm';
m1[28] = 'k';
m1[10] = 'x';
m1[30] = 'a';
m1[15] = 'b';
map<int, char>::iterator it1;
for(it1 = m1.begin(); it1 != m1.end(); it1++)
{
cout<< (*it1).first << " : " << (*it1).second <<endl;
}
cout<< endl;
m1.erase(28);
for(it1 = m1.begin(); it1 != m1.end(); it1++)
{
cout<< (*it1).first << " : " << (*it1).second <<endl;
}
cout<< endl;
it1 = m1.begin();
m1.erase( it1++, m1.end());
for(it1 = m1.begin(); it1 != m1.end(); it1++)
{
cout<< (*it1).first << " : " << (*it1).second <<endl;
}
cout<< endl;
元素反向遍历:
map<int, char>::reverse_iterator rit;
for(rit = m1.rbegin(); rit != m1.rend(); rit ++)
{
cout<<(*rit).first << " : " << (*rit).second <<endl;
}
元素搜索:
使用find方法来搜索某个键值,如果搜索到了,则返回该键值所在的迭代器位置,否则返回end()的值。
cout<< endl;
it1 = m1.find(10);
if(it1 != m1.end())
{
cout<<(*it1).first << " : " << (*it1).second <<endl;
}
自定义比较函数,与set的自定义比较函数完全相同,其使用也完全相同
一般类型的比较函数:
struct myComp
{
bool operator()(const int &a, const int &b)
{
if(a!=b)
return a > b;
else
return a > b;
}
};
map<int ,char, myComp> m2;
m2[25] = 'm';
m2[28] = 'k';
m2[10] = 'x';
m2[30] = 'a';
m2[15] = 'b';
map<int ,char, myComp>::iterator it2;
for(it2 = m2.begin(); it2 != m2.end(); it2++)
{
cout<< (*it2).first << " : " << (*it2).second <<endl;
}
cout<< endl;
键值为结构体的形式:
struct Info
{
string name;
float score;
bool operator < (const Info &a) const
{
return a.score < score;
}
};
map<Info, int> mstrct;
Info info;
info.name = "Jack";
info.score = 80.5;
mstrct[info] = 25;
info.name = "Tomi";
info.score = 20.5;
mstrct[info] = 10;
info.name = "Nacy";
info.score = 60.5;
mstrct[info] = 30;
map<Info, int>::iterator itstrct;
for( itstrct = mstrct.begin(); itstrct != mstrct.end(); itstrct++)
{
cout<<(*itstrct).second <<" : ";
cout<<((*itstrct).first).name<< " " << ((*itstrct).first).score <<endl;
}
map实现数字分离:
数字的各位数进行分离,采用取余等方法非常耗时,可以把数字当成字符串使用map的映射进行分离。
map<char, int> mnum;
mnum['0'] = 0;
mnum['1'] = 1;
mnum['2'] = 2;
mnum['3'] = 3;
mnum['4'] = 4;
mnum['5'] = 5;
mnum['6'] = 6;
mnum['7'] = 7;
mnum['8'] = 8;
mnum['9'] = 9;
string sa, sb;
sa = "6234";
int sum = 0;
for(int i = 0; i < sa.length(); i++)
{
sum += mnum[sa[i]];
}
cout << "sum= " << sum <<endl;
数字映射为字符的map写法:
map<int, char> mchar;
for(int j = 0; j < 10; j++)
{
mchar[j] = '0' + j;
}
int n = 7;
string s = "The number is ";
cout << s + mchar[n] <<endl;
6. multimap多重映射容器:
multimap允许插入重复键值的元素,由于存在重复键值,所以元素的插入,删除,查找与map不相同
multimap也位于 #include<map>中
#include <iostream>
#include <map>
#include <string>
using namespace std;
int main()
{
multimap<string, double> m;
m.insert(pair<string, double>("Jack", 300.5));
m.insert(pair<string, double>("Kity", 200));
m.insert(pair<string, double>("Memi", 500));
m.insert(pair<string, double>("Jack", 233));
multimap<string, double>::iterator it;
for(it = m.begin(); it!= m.end(); it++)
{
cout<<(*it).first << " : " << (*it).second <<endl;
}
return 0;
}
元素的删除:
m.erase("Jack");
for(it = m.begin(); it!= m.end(); it++)
{
cout<<(*it).first << " : " << (*it).second <<endl;
}
删除掉元素,与set类似,可以删除一个元素,区间内元素,如果存在重复的键,则全部删除
元素查找:
it = m.find("Jack");
if(it!= m.end())
{
cout<<(*it).first << " " << (*it).second << endl;
}
else
{
cout<< "Not find!" <<endl;
}
如果是重复的键,则值返回第一个键的迭代器。
7. deque 双端队列容器:
deque和vector一样,采用线性表顺序存储结构。deque采用分块的线性存储结构来存储数据。每一块一般为512字节。
所有的deque块用Map块进行管理,每个Map数据项纪录各个deque的首地址。
这样就可以在头部和尾部插入和删除元素,而不需要移动其他的元素。
当考虑容器元素的内存分配策略和操作的性能时,deque相对于vector有优势。
deque块
—— ————— ——
—— ————— ——
—— ————— ——
| | 块1 | |
| | 块3 | |
| | 块3 | |
—— ————— ——
—— ————— ——
—— ————— ——
| | |
| |----------------| |
| | |------------------------------
—— —— ——
| | | | Map
—— —— ——
deque存在于 #include<deque>
#include <iostream>
#include <deque>
using namespace std;
int main()
{
deque<int> d;
d.push_back(1);
d.push_back(2);
d.push_back(3);
d.push_back(4);
cout<< d[0] << " " << d[1] << " " << d[2] << endl;
return 0;
}
上述从尾部插入数据,队列不断地进行扩张,
从头部插入数据,增加新元素,原有的元素向后一次错位
d.push_front(10);
d.push_front(20);
cout<< d[0] << " " << d[1] << " " << d[2] << endl;
从中间插入元素也增加新元素,该元素后面原来的元素一次向后进行错位。
d.insert(d.begin() + 1, 88);
cout<< d[0] << " " << d[1] << " " << d[2] << endl;
前向遍历:
以数组方式遍历:
int i = 0;
for( i = 0; i < d.size(); i++)
{
cout<< d[i] <<" ";
}
cout<<endl;
以迭代器的方式进行遍历:
deque<int>::iterator it;
for( it = d.begin(); it != d.end(); it++)
{
cout<< *it << " ";
}
cout<<endl;
反向遍历,采用方向迭代器对双端队列容器进行方向遍历:
deque<int>::reverse_iterator rit;
for( rit = d.rbegin(); rit != d.rend(); rit++)
{
cout<< *rit << " ";
}
cout<<endl;
删除元素:
使用pop_front()方法:
d.pop_front();
d.pop_front();
for( it = d.begin(); it != d.end(); it++)
{
cout<< *it << " ";
}
cout<<endl;
使用pop_back()方法:
d.pop_back();
d.pop_back();
for( it = d.begin(); it != d.end(); it++)
{
cout<< *it << " ";
}
cout<<endl;
使用erase从中间删除元素:
d.erase(d.begin() + 1);
for( it = d.begin(); it != d.end(); it++)
{
cout<< *it << " ";
}
cout<<endl;
清空元素
d.clear();
cout<< d.size() <<endl;
8. list双向链表容器
list实现的是双向列表的数据结构,数据元素通过链表指针串联成逻辑意义上的线性表。队列表任一位置的元素进行插入删除和查找
都是极快速的。
由于list独享的节点不要求在一段连续的内存中,,所以对于迭代器只能通过 ++ 或者-- 的操作将迭代器移动到后继或前驱节点。
不能进行+n 或 -n的操作。
list包含在 #include<list>中
#include <iostream>
#include <list>
using namespace std;
int main()
{
list<int> l;
l.push_back(2);
// 从列表尾部插入一个元素
l.push_back(1);
l.push_back(5);
l.push_front(8);
// 从列表前插入一个元素
list<int>::iterator it;
it = l.begin();
it ++;
l.insert(it, 20);
// 在列表中,以it位置处插入一个元素
for(it = l.begin(); it != l.end(); it++)
{
cout<< *it << " ";
}
cout<< endl;
return 0;
}
反向遍历:
list<int>::reverse_iterator rit;
for(rit = l.rbegin(); rit != l.rend(); rit++)
{
cout << *rit << " ";
}
元素删除:
使用remove方法,删除所有等于1的元素。
l.push_front(1);
for(it = l.begin(); it != l.end(); it++)
{
cout<< *it << " ";
}
cout<< endl;
l.remove( 1);
for(it = l.begin(); it != l.end(); it++)
{
cout<< *it << " ";
}
cout<< endl;
使用pop_front()方法, 使用pop_back()方法.
l.pop_front();
l.pop_back();
for(it = l.begin(); it != l.end(); it++)
{
cout<< *it << " ";
}
cout<< endl;
使用erase方法
it = l.begin();
it++;
l.erase(it);
// 删除指定位置的元素
for(it = l.begin(); it != l.end(); it++)
{
cout<< *it << " ";
}
cout<< endl;
l.clear();
// 清除所有的元素
cout<< l.size() << endl;
查找元素:
使用find()查找算法,如果找到则返回该元素的迭代器位置,如果没有找到返回end()的值。
find()查找算法位于 #include<algorithm>
it = find(l.begin(), l.end(), 5);
if(it != l.end())
{
cout<< "find it" << endl;
}
else
{
cout<< "not find it" << endl;
}
元素排序:
采用sort方法可以链表元素进行升序排序:
l.sort();
for(it = l.begin(); it != l.end(); it++)
{
cout<< *it << " ";
}
cout<< endl;
剔去连续重复元素,使用unique方法:
l.push_back(5);
l.push_back(5);
for(it = l.begin(); it != l.end(); it++)
{
cout<< *it << " ";
}
cout<< endl;
l.unique();
for(it = l.begin(); it != l.end(); it++)
{
cout<< *it << " ";
}
cout<< endl;
注意:此处剔除的是 "连续"重复元素,也即不连续的重复元素是不剔除的。
9. bitset位集合容器:
bitset容器是一个bit位元素的序列容器,每个元素只占用一个bit位。取值为0或1,因此很节省空间。
bitset位于 #include<bitset> 中
bitset的方法列表
b.any();
是否存在一位为1
b.none();
是否不存在为1 的一位
b.count();
置为1的位数
b.size();
二进制数位的个数
b[pos];
b中pos处的二进制位
b.test(pos);
b中pos位是否为1
b.set();
所有二进制位都设置为1
b.set(pos);
指定pos处为1
b.reset();
二进制位都设置为0
b.reset(pos);
pos处二进制位设置为0
b.flip();
b中二进制位逐位取反
b.flip(pos);
pos处的二进制位取反
b.to_ulong();
用b中同样的二进制位返回一个unsigned long值
os<<b;
b中位集输出到os流
#include <iostream>
#include <bitset>
using namespace std;
int main()
{
bitset<10> b;
b[1] = 1;
b[6] = 1;
b[9] = 1;
int i = 0;
for( i = b.size() - 1; i >= 0; i--)
{
cout << b[i];
}
cout<< endl;
return 0;
}
采用set()方法,一次性将元素设置为1.
b.set();
for( i = b.size() - 1; i >= 0; i--)
{
cout << b[i];
}
cout<< endl;
采用set(pos)方法将pos位设置为1。
b.reset();
b.set(4);
b.reset(5);
for( i = b.size() - 1; i >= 0; i--)
{
cout << b[i];
}
cout<< endl;
除了采用下标法输出元素之外,可以直接输出bitset的元素:
cout<< b <<endl;
10. stack堆栈容器:
stack是一个先进先出的线性表。插入与删除都从列表一段进行。
入栈 与 出栈
stack位于 #include<stack>中
#include <iostream>
#include <stack>
using namespace std;
int main()
{
stack<int> s;
s.push(1);
s.push(2);
s.push(3);
cout<< s.top() <<endl;
cout << s.size() <<endl;
cout << s.empty() << endl;
while(s.empty() != true)
{
cout<< s.top() << " ";
s.pop();
}
cout << endl;
return 0;
}
11. queue队列容器:
队列容器是一个先进先出的线性存储表,元素插入只能在队尾。
queue包含在#include<queue> 中
queue具有 入队 push(), 出队 pop() 读取队头元素 front() 读取队尾元素 back(),判断是否为空empty() 和队列当前元素的数目size()
等方法。
#include <iostream>
#include <queue>
using namespace std;
int main()
{
queue<int> q;
q.push(1);
q.push(2);
q.push(3);
q.push(9);
cout<< q.empty() <<endl;
cout<< q.front() <<endl;
cout<< q.back() << endl;
while(q.empty() != true)
{
cout<<q.front() << " ";
q.pop();
}
cout<<endl;
return 0;
}
12. priority_queue优先队列
priority_queue优先队列容器与队列一样,只能从队尾插入元素,从队首删除元素。
它有一个特性,就是最大的元素始终位于队首,出队时,并非按照先进先出的顺序,而是将当前队列中最大的元素出队。
类似与将队列元素进行由大到小的排序。当然可以重载 "<" 操作符来重新定义比较规则。
priority_queue位于 #include<queue>中
优先队列包括 入队push() 出队pop() 队首元素top(),判断是否为空empty()以及队列的大小size()
#include <iostream>
#include <queue>
using namespace std;
int main()
{
priority_queue<int> pq;
pq.push(1);
pq.push(2);
pq.push(3);
pq.push(9);
cout<< pq.size()<<endl;
while(pq.empty() != true)
{
cout<< pq.top() << " ";
pq.pop();
}
cout<<endl;
return 0;
}
重载 "<" 操作符来定义优先级:
struct Info
{
string name;
float score;
bool operator < (const Info &a) const
{
return a.score < score;
}
};
priority_queue<Info> pqstrct;
Info info;
info.name = "Jack";
info.score = 80.5;
pqstrct.push(info);
info.name = "Tomi";
info.score = 20.5;
pqstrct.push(info);
info.name = "Nacy";
info.score = 60.5;
pqstrct.push(info);
while( pqstrct.empty() != true)
{
cout<< pqstrct.top().name << " : " << pqstrct.top().score <<endl;
pqstrct.pop();
}
重载 "()" 来重新定义优先级:
struct myComp
{
bool operator()(const int &a, const int &b)
{
if(a!=b)
return a > b;
else
return a > b;
}
};
priority_queue<int, vector<int>, myComp> pqfun;
pqfun.push(1);
pqfun.push(8);
pqfun.push(3);
pqfun.push(30);
while(pqfun.empty() != true)
{
cout<< pqfun.top() << " ";
pqfun.pop();
}
cout<<endl;
By Andy