C++STL泛型编程基础知识讲解--------2015年2月3日
今天学习了C++STL泛型编程的基础知识,我对主要知识整理如下:
STL提供三种类型的组件:容器,迭代器,算法。支持泛型程序设计标准。
容器主要有两类:顺序容器和关联容器。
顺序容器:vector,list,deque,string等都是一系列连续元素的集合。
关联容器:set,multiset,map,multimap包含查找元素的键值。
迭代器:遍历容器
STL算法库:排序算法,不可变序算法,变序性算法,数值算法。
/*******************************************************************************************************/
Vector容器简介
(1)优势:可以随机访问各个元素还可以在尾部添加元素。因此可以完全代替数组。具有内存自动管理功能,可以随时动态调整内存功能。
(2)基本内容
头文件声明:#include<vector>
vector容器是从下标0开始计数,我们可以事先固定一个大小,事后可以随时调整其大小;也可事先不定义,随时使用push_back()方法从尾部扩张,也可以使用insert()方法在某个元素位置前插入元素。
vector容器的两个重要方法:
begin()和end():begin()方法返回首元素位置的迭代器,end()方法返回最后一个元素的下一个元素的位置的迭代器。
(3)创建对象
法1:vector<int>v;
法2:vector<double>v(10);(固定大小)
法3:vector<double>v(10,8.6);(固定了大小并且初始化)
(3)元素的尾部扩张
#include<iostream>
#include<vector>
using namespace std;
int main()
{
vector<int>v;
v.push_back(2);
v.push_back(7);
v.push_back(9);
return 0;
}
(4)下标访问vector元素
#include<iostream>
#include<vector>
using namespace std;
int main()
{
vector<int>v(3);
v[0]=2;
v[1]=7;
v[2]=9;
cout<<v[0]<<v[1]<<v[2]<<endl;
return 0;
}
(5)使用迭代器访问vector元素
迭代器的类型必须与遍历的vector对象的元素的类型一致
#include<iostream>
#include<vector>
using namespace std;
int main()
{
vector<int>v;
v.push_back(3);
v.push_back(6);
v.push_back(9);
vector<int>::iterator it;
for(it=v.begin();it!=v.end();it++)
{
cout<<*it<<endl;
}
return 0;
}
(6)元素的插入
insert()方法可以在vector对象的任意位置之前插入一个新的元素,同时vector自动扩张一个元素的空间,插入位置后所有元素依次向后挪动一个位置。
#include<iostream>
#include<vector>
using namespace std;
int main()
{
vector<int>v(3);
v[0]=1;
v[1]=3;
v[2]=6;
v.insert(v.begin(),8);
v.insert(v.begin()+2;9);//在第二个元素前插入元素9
for(it=v.begin();it!=v.end();it++)
{
cout<<*it<<endl;
}
return 0;
}
(7)元素的删除
erase()方法可以删除vector中迭代器所指的一个元素或者一段区间的所有元素。clear()方法可以删除所有元素。
#include<iostream>
#include<vector>
using namespace std;
int main()
{
vector<int>v(3);
v[0]=1;
v[1]=3;
v[2]=6;
v.erase(v.begin()+2);//删除第二个元素
v.erase(v.begin(),v.end());//删除所有元素
return 0;
}
(8)元素的反转
reverse()方法:头文件是#include<algorithm>
reverse(v.begin(),v.end());
(9)元素排序
sort()方法:头文件#include<algorithm>
默认方法是升序
可以自定义排序方法:
bool cmp(const int &a,const int &b)
{
return a>b;
}
sort(v.begin(),v.end(),cmp);
(10)向量的大小
size()方法和empty()方法
v.size()和v.empty()。
/************************************************************************************************/
string 容器简介:
(1)创建string对象
string s;//初试长度为0
(2)给string对象赋值
法1:s="sjdjfj';
法2:char ss[20];
scanf("%s",ss);
s=ss;
(3)string对象尾部添加字符
s=s+'a';
(4)string对象尾部添加字符串
法1:s=s+"abc";
法2:s.append("abc");
(5)string对象插入字符
string::iterator it=s.begin();
s.insert(it+1,'a');
(6)访问string对象元素
s="acffggg";
cout<<s[0];
(7)删除string对象的元素
1.清空字符串可以直接赋值空字符串即可;
2.使用erase()方法删除迭代器所指的那个元素或者那个区间所有元素;
string s="aaaaffggg";
string::iterator it=s.begin();
s.erase(it+1);
s.erase(it+1,it+4);
(8)返回string对象的长度以及判断是否为空
s.length()及s.empty();
(9)替换string中的字符
s.replace(3,3,"gppg");//从第三个字符开始将连续的3个字符替换为"gppg"
(10)搜索string对象的元素或者子串
采用find()方法:查找一个字符用单引号‘’界定;查找一个字符串用双引号""界定。
s.find('c');
s.find("sdd");
(11)string对象的比较
string对象可以用compare()方法与其它字符串进行比较,如果它比对方大,则返回1;如果它比对方小,则返回-1;
如果它与对方相同,则返回0.
s.compare("ssfgg");
(12)反向排序string对象
reverse()方法:头文件#include<algorithm>
reverse(s.begin(),s.end());
(13)string对象作为 vector元素
vector<string>v;
v.push_back("jack");
v.push_back("shfj");
cout<<v[0]<<v[1]<<endl;
cout<<v[0][0]<<endl;
cout<<v[0].length()<<endl;
(14)string对象与字符数组互操作
char ss[100];
scanf("%s",ss);
s=ss;
printf(s.c_str());
cout<<endl;
printf("%s",ss);
(15)string对象与sscanf函数
string s1,s2,s3;
char sa[100],sb[100],sc[100];
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;
int x,y,z;
sscanf("4,5$6","%d,%d$%d",&x,&y,&z);
cout<<x<<' '<<y<<' '<<z<<endl;
(16)string对象与数值相互转换
#include<iostream>
#include<vector>
#include<sstream>
#include<string>
using namespace std;
string convertToString(double x)
{
ostringstream o;
if(o<<x) return o.str();//将变量x读取到字符流o中
return "error";
}
double convertFromString(const string &s)
{
istringstream i(s);
double x;
if(i>>x) return x;//相当于把字符串从字符流中读取到变量x中
return 0.0;
}
int main()
{
char b[10];
string a;
sprintf(b,"%d",1975);
a=b;
cout<<a<<endl;
string cc=convertToString(1976);
cout<<cc<<endl;
string dd="2006";
int p=convertFromString(dd)+2;
cout<<p<<endl;
return 0;
}
/***************************************************************************************************/
set集合容器(红黑树原理)
(1)创建set集合对象
set<int>s;
(2)元素的插入和中序遍历,反向遍历(使用前向迭代器)
#include<set>
#include<iostream>
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;
set<int>::reverse_iterator rit;//反向遍历
for(rit=s.rbegin();rit!=s.rend();rit++)
{
cout<<*rit<<endl;
}
return 0;
}
(3)元素的删除
#include<set>
#include<iostream>
using namespace std;
int main()
{
set<int>s;
s.insert(8);
s.insert(1);
s.insert(12);
s.insert(6);
s.insert(8);//重复,不执行插入操作
s.erase(6);//删除元素6(键值)
set<int>::reverse_iteerator rit;
for(rit=s.rbegin();rit!=s.rend();rit++)
cout<<*rit<<endl;
cout<<s.size()<<endl;
return 0;
}
(4)元素的检索
使用find()方法进行搜索,查到以后返回该键值在迭代器中的位置,否则返回最后一个元素后面的一个位置,即end()。
set<int>::iterator it;
it=s.find(6);
if(it!=s.end()) cout<<*it<<endl;
(5)自定义比较函数
案例1:
#include<set>
#include<iostream>
using namespace std;
struct mycomp
{
bool operator()(const int &a,const int &b)
{
return a>b;
}
};
int main()
{
set<int,mycomp>s;
s.insert(3);
s.insert(7);
s.insert(11);
s.insert(12);
set<int,mycomp>::iterator it;
for(it=s.begin();it!=s.end();it++)
{
cout<<*it<<endl;
}
return 0;
}
案例2:
#include<set>
#include<iostream>
using namespace std;
struct info
{
string name;
float score;
bool operator<(const info &a)const
{
return a.score<score;
}
};
int main()
{
set<info>s;
info ifo;
ifo.name="dd";
ifo.score=999;
s.insert(ifo);
ifo.name="ss";
ifo.score=799;
s.insert(ifo);
set<info>::iterator it;
for(it=s.begin();it!=s.end();it++)
cout<<*it<<endl;
return 0;
}
multiset多重集合容器(可重复元素的红黑树原理)
(1)multiset元素的插入(头文件依然是#include<set>)
#include<set>
#include<string>
#include<iostream>
using namespace std;
int main()
{
multiset<string>s;
s.insert("aad");
s.insert("bbc");
multiset<string>::iterator it;
for(it=s.begin();it!=s.end();it++)
cout<<*it<<endl;
return 0;
}
(2)multiset元素的删除
采用erase()方法可以删除multiset对象中的某个迭代器位置上的元素,某段迭代器区间中的元素,键值等于某个值的所有重复元素,并返回删除元素的个数。采用clear()方法可以清空元素。
#include<set>
#include<string>
#include<iostream>
using namespace std;
int main()
{
multiset<string>s;
s.insert("ssjj");
s.insert("ssjj");
s.insert("dggh");
multiset<string>::iterator it;
int n=s.erase("ssjj");
for( it=s.begin();it!=s.end();it++)
cout<<*it<<endl;
return 0;
}
(3)查找元素
find方法查找元素如果找到,返回该元素的迭代器位置(如果元素重复,返回第一个重复元素的迭代器位置);如果没有找到,则返回end()迭代器位置。
#include<set>
#include<string>
#include<iostream>
using namespace std;
int main()
{
multiset<string>s;
s.insert("abc");
s.insert("def");
s.insert("hgjj");
multiset<string>::iterator it;
it=ms.find("abc");
if(it!=s.end())
cout<<*it<<endl;
return 0;
}
/******************************************************************************************/
map容器简介
map容器的数据结构采取的是红黑树来实现的,插入元素的键值不允许改变,比较函数只对元素的键值进行比较。
(1)创建map对象
键值与映照数据的类型自己定义。
#include<map>
#include<iostream>
#include<string>
using namespace std;
int main()
{
map<string,float>m;
m["jack"]=98.5;
m["bomi"]=96;
m["kagr"]=67;
map<string,float>::iterator it;
for(it=m.begin();it!=m.end();it++)
cout<<(*it).first<<' '<<(*it).second<<endl;
return 0;
}
(2)删除元素
采用erase()函数可以删除一个元素,一段元素,键值重复的元素。
#include<iostream>
#include<string>
#include<map>
int main()
{
map<int,char>s;
s[1]='a';
s[20]='t';
s[15]='v';
s.erase(20);
map<int,char>::iterator it;
for(it=s.begin();it!=s.end();it++)
cout<<(*it).second<<endl;
return 0;
}
(3)元素的反向遍历
使用迭代器reverse_iterator反向遍历和rbegin(),rend()方法进行遍历。
#include<map>
#include<string>
#include<iostream>
using namespace std;
int main()
{
map<int,char>s;
s[1]='a';
s[2]='b';
s[20]='f';
map<int,char>::reverse_iterator rit;
for(rit=s.rbegin();rit!=s.rend();rit++)
cout<<(*rit).first<<' '<<(*rit).second<<endl;
return 0;
}
(4)元素的搜索
使用find()方法搜索某个键值,搜索到以后返回所在的迭代器位置,否则返回end()迭代器位置。
法1:
#include<map>
#include<string>
#include<iostream>
using namespace std;
int main()
{
map<int,char>s;
s[1]='a';
s[2]='b';
s[20]='f';
map<int,char>::iterator it;
it=s.find(2);
if(it!=s.end())
cout<<(*it).first<<' '<<(*it).second<<endl;
return 0;
}
(5)自定义比较函数
默认函数排序是按照键值从小到大的顺序插入元素
#include<iostream>
#include<string>
#include<map>
using namespace std;
struct mycomp
{
bool operator()(const int &a,const int &b)
{
return a>b;
}
};
int main()
{
map<int,char,mycomp>m;
m[25]='m';
m[28]='f';
m[10]='a';
map<int,char,mycomp>::iterator it;
for(it=m.begin();it!=m.end();it++)
{
cout<<(*it).first<<' '<<(*it).second<<endl;
}
return 0;
}
法2:
#include<iostream>
#include<string>
#include<map>
using namespace std;
struct info
{
string name;
float score;
bool operator<(const info &a)const
{
return a.score<score;
}
};
int main()
{
map<info,int>m;
info ifo;
ifo.name="sdj";
ifo.score=80;
m[ifo]=25;
map<info,int>::iterator it;
for(it=m.begin();it!=m.end();it++)
{
cout<<(*it).second;
cout<<((*it).first).name<<' '<<((*it).first).score<<endl;
}
return 0;
}
Application:
1.map容器实现数字分离
#include<string>
#include<map>
#include<iostream>
int main()
{
map<char,int>m;
for(int i=0;i<10;i++)
{
m['0'+j]=j;
}
string sa;
sa="asddddd";
int sum=0;
for(int i=0;i<sa.length();i++)
sum+=m[sa[i]];
cout<<sum<<endl;
return 0;
}
2.map容器实现数字印照字符
#include<iostream>
#include<map>
#include<string>
int main()
{
map<int,char>m;
for(int i=0;i<10;i++)
m[j]='0'+j;
string a="the number is:";
cout<<s+m[7]<<endl;
return 0;
}
/******************************************************************************************************/
multimap容器简介
(1)元素的插入
#include<iostream>
#include<map>
#include<string>
using namespace std;
int main()
{
mmultimap<string,double>m;
m.insert(pair<string,double>("jack",300.5));
m.insert(pair<string,double>("lan",5868));
m.insert(pair<string,double>("hdhf",6886));
multimap<string,double>::iterator it;
for(it=m.begin();it!=m.end();it++)
cout<<(*it).first<<' '<<(*it).second<<endl;
return 0;
}
(2)元素的删除
#include<iostream>
#include<map>
#include<string>
using namespace std;
int main()
{
multimap<string,double>m;
m.insert(pair<string,double>("jack",300.6));
m.insert(pair<string,double>("jsjjd",300.56));
m.insert(pair<string,double>("djj",384));
m.erase("jack");
multimap<string,double>::iterator it;
for(it=m.begin();it!=m.end();it++)
cout<<(*it).first<<' '<<(*it).second<<endl;
return 0;
}
(3)元素的查找
采用find()方法,如果找到则返回第一个键值的下标,否则返回end()迭代器位置。
/******************************************************************************************/
list双向链表容器
list每个节点有三个域:前驱元素指针域,数据域,后继元素指针域
对于迭代器只能通过“++”或者“--”的操作将迭代器移动到后继/前驱节点上,不能执行操作"+n"或者"-n";
(1)创建list对象
1.创建空链表:list<int>m;
2.创建具有n个元素的链表:list<int>m(10);
(2)元素的插入与遍历
采用push_back(),push_front(),insert()方法进行。
#include<list>
#include<iostream>
using namespace std;
int main()
{
list<int>m;
m.push_back(2);
m.push_back(6);
m.push_front(9);
list<int>::iterator it;
it++;
m.insert(it,20);
for(it=m.begin();it!=m.end();it++)
cout<<(*it)<<endl;
return 0;
}
(3)反向遍历
采用反向迭代器reverse_iterator加rbegin(),rend()方法进行反向遍历
(4)元素删除
1.使用remove()方法删除链表中一个元素值相同的元素都会被删除;
2.使用pop_front()和pop_back()方法进行删除首尾元素;
3.使用erase()方法删除迭代器位置上的元素;
list<int>::iterator it;
it=s.begin();
it++;
s.erase(it);
4.使用clear()方法清空list
(4)元素查找
使用find()方法查找:
list<int>::iterator it;
it=find(l.begin(),l.end(),7);
if(it!=l.end())
cout<<*it<<endl;
(5)元素排序
使用sort()方法
(6)剔除连续重复元素
使用unique()方法
/**************************************************************************************/
priority_queue优先队列容器
push():插入元素
pop():删除元素
top():读取队首元素
empty():是否为空
size():读取元素数量
重载<操作符定义优先级
struct info
{
string name;
float score;
bool operator<(const Info &a)const
{
return a.score<score;
}
};
priority_queue<info>q;
重载“()”操作符定义优先级
struct mycomp
{
bool operator()(const int &a,int &b)
{
return a>b;//这里与其它容器相反,>表示从小到大排列,<表示从大到小排列
}
};