STL学习与示例

STL的本质就是:类模板,函数模板,运算符重载.说起来也是"多态"的表现形式,只不过具有高超的编程技巧和运用,能减少程序员的很多繁琐重复的工作,是一个优秀的"库".
       
        STL提供六大组件,彼此可以组合套用,共同组合成STL丰富多彩的编程应用:
1)容器(containers):各种数据结构(基本上就是集合类.容器是STL的最主要的标志,可以浅显得认为STL就是容器类的集合...)
 如:vector,list,deque,set,map,用来存放数据.

2)算法(algorithms):各种常用算法如:sort,search,copy,erase...

3)迭代器(iterator):
 扮演容器与算法直接的胶合剂,所所谓的"泛型指针".(我靠,本质还是从指针来的,只不过"变异"了..)
 共有5种类型,以及其他衍生变化:

4)仿函数(functors):行为类似函数,可作为算法的某种策略.(靠,其实就是类....)
 仿函数是一种重载了operator()的class或class template,一般函数指针可看作为狭义的仿函数.

5)配接器(adapters):(其实就是C#中的接口啦!!!)
 一种用来修饰容器(containers)或仿函数或迭代器接口的东西.

6)配置器(allocators):
 负责空间配置与管理.
 是一个实现了动态空间配置/空间管理/空间释放 的class template.

        OK.STL就是容器类+算法实现+迭代器+配接器+仿函数+配置器.

         容器通过配置器取得数据存储空间,算法通过迭代器存取容器内容,仿函数可以协助算法完成不同的策略变化,配接器可以修饰或套界仿函数.

以下着重说明STL的容器类以及一些基本的算法:
 
STL容器              所在头文件         特性
向量vector             <vector>     相当于多功能数组,但是最好不要对向量头进行添加或删除操作
双端队列deque     <deque>      基本与vector一样
表list                       <list>          对某一位置插入和删除操作花费小
队列queue             <queue>      插入只可以在尾部,删除/检索和修改只能在头部.先进先出(与stack相反)
堆栈stack              <stack>       后进先出
集合set                  <set>          每个节点包含一个元素,查找十分快速,不支持重复元素
多重集合multiset   <set>          和集合基本相同,支持重复元素
映射map                <map>       由键/值对组成的集合.(不能有重复键)
多重映射multimap <map>        可以有重复键.

        很多功能,可以用不同的容器来实现(这点很重要),但是要考虑实际的需要,选择合适的容器将大大提高程序性能.(对于新手来说,嘿嘿,能用就好,用顺手了,好好比较下不同情况下不同容器实现相同功能的效率撒...)

STL算法:主要头文件<algorithm>,<numeric>,<functional>.
<algorithm>:由模板函数组成.常用功能算法:比较,交换,查找,遍历,复制,修改,移除,反转,排序,合并等.
<numeric>:包含几个在序列上进行简单数学运算的模板函数,包括加法和乘法在序列上的一些操作.
<functional>:定义了一些模板类,即仿函数.      

STL迭代器:<iterator> (注意,可以把迭代器理解为指针,但是不能像指针一样使用迭代器...)
迭代器功能                               功能              头文件
输入迭代器(Input iterator)         向前读          istream
输出迭代器(Output iterator)      向前写          ostream,inserter
前向迭代器(Forward iterator)   向前读写
双向迭代器                               向前向后读写 list,set,vector,map,multimap,deque,queue
随即迭代器                               随即读写 vector,deque,array,string


1)构造STL容器对象
#include <iostream>
#include <vector>
using namespace std;

class VS
{
public:
 static void Show(vector<int> iv)
 {
  for(vector<int>::iterator iter=iv.begin(); iter!=iv.end(); iter++)
   cout<<*iter<<endl;
  cout<<"-----------------------------------------------"<<endl;
 }
};
void main()
{
 vector<int> iv1;   //构造方法1,默认构造无元素,使用push_back方法向容器中添加元素
 iv1.push_back(11);
 iv1.push_back(222);
 VS::Show(iv1);
 
 vector<int> iv2(2);   //构造方法2,构造2个int元素,默认初始值为0
 VS::Show(iv2);

 vector<int> iv3(3,1);  //构造方法3,构造3个int元素,指定初始值为1
 VS::Show(iv3);

 int a[] = {1,2,343,542,22}; //构造方法4,从数组中直接构造容器元素
 vector<int> iv4(a,a+5);
 VS::Show(iv4);

 vector<int> iv5(iv4);  //构造方法5,从其他容器中直接构造本容器元素
 VS::Show(iv5);

 vector<int>::iterator iter = iv4.begin(); //构造方法6,使用迭带器指针构造
 vector<int> iv6(iter+1,iter+3);
 VS::Show(iv6);

 cin.get();
}

//2)容器类的几种输出方式
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;

template<typename T>
class print  //仔细看了,print其实是一个类,只不过重载了"()"运算符,使用起来就像函数,所以称为"仿函数"
{
public:
 void operator()(const T& elem)
 {
  cout<<elem<<"  ";
 }
};

void show(const vector<int>& iv)
{
 for (int i=0; i<iv.size(); i++)
  cout<<iv[i]<<"  ";
 cout<<endl<<"-----------------------------------"<<endl;
}
void display(const vector<int>& iv)
{
 for (vector<int>::const_iterator iter=iv.begin(); iter!=iv.end(); iter++)
  cout<<*iter<<"  ";
 cout<<endl<<"-----------------------------------"<<endl;
}

void main()
{
 int ia[6] = {0,1,2,3,4,5};
 vector<int> iv(ia,ia+6);
 show(iv);              //1)传统的索引输出
 display(iv);             //2)使用迭代器输出
 for_each(iv.begin(),iv.end(),print<int>());      //3)使用for_each方法输出,需要配合自定义输出函数
 cout<<endl<<"------------------------------------"<<endl;
 copy(iv.begin(), iv.end(), ostream_iterator<int>(cout, "  ")); //4)使用copy方法,调用系统输出函数
 cin.get();
}
//3)STL算法:演示sort排序和reverse翻转(这两个方法配合,就可以实现从小到大和从大到小排序了)
#include <iostream>
#include <algorithm>
using namespace std;

int main()
{
 int a[10] = {12,0,5,3,6,8,9,34,32,18};
 int b[5]  = {5,3,6,8,9};
 int d[15];
 sort(a,a+10);   //sort是从小到大排序,要实现从大到小排序,使用reverse方法翻转即可
 for (int i=0; i<10; i++)
 {
  cout<<" "<<a[i];
 }
 cout<<endl;

 sort(b,b+5); //b数组排序好,判断是否包含在排序好的a数组中

 if(includes(a,a+10,b,b+5))  //includes方法判断一个数组是否是另一个数组的子集合...
  cout<<"sorted b members are included in a.";//这里,可以发现数组a中也有"3,5,6,8,9"元素
 else
  cout<<"sorted a dosn't contain sorted b!";
 
 cout<<endl;

 reverse(a,a+10);  //翻转
 for (int i=0; i<10; i++)
 {
  cout<<" "<<a[i];
 }
 cout<<endl;

 cin.get();
 return 0;
}
//4)list列表容器,很常用的.
#include <iostream>
#include <list>    //使用list容器,必须加此头文件
using namespace std;

void main()
{
 list<int> pp;    //声明int元素类型的list容器对象

 for (int i=0; i<=9; i++)//后插
 {
  pp.push_back(i);//在当前list<int>容器的最后位置插上i的值
  pp.push_front(i*i); //在头部插入元素
  //insert()  在任意指定位置插入元素
 
 }
 //使用迭代器pi进行循环迭代输出pp容器中的所有元素
 copy(pp.begin(),pp.end(),ostream_iterator<int>(cout," "));
 cout<<endl<<"-----------------------------------------"<<endl;
 //按常规做法进行迭代输出是不行的,因为list容器是用链表构建的,不支持随即访问功能(这点要注意)
 //for (int i=0; i<pp.size(); i++)
 //{
 // cout<<pp[i]<<" ";
 //}
 cout<<pp.front()<<endl; //返回头元素
 cout<<pp.back()<<endl; //返回尾元素
 cout<<pp.size()<<endl; //显示此容器的所有元素个数

 pp.pop_back();   //移除最后一个元素
 pp.pop_front();   //移除最前一个元素
 copy(pp.begin(),pp.end(),ostream_iterator<int>(cout," "));
 cout<<endl<<"-----------------------------------------"<<endl;

 cout<< pp.max_size()<<endl; //此list容器所能申请的最大空间

 list<int>::iterator pi = pp.begin();  //声明迭代器pi,用来操纵list<int>容器对象
 pp.assign(2,3);    //assign是重新分配和构造的方法
 copy(pp.begin(),pp.end(),ostream_iterator<int>(cout," "));
 cout<<endl<<"-----------------------------------------"<<endl;

 list<int> ppp;
 cout<<ppp.empty()<<endl;  //empty方法判断容器是否为空
 cout<< pp.empty()<<endl;  //可以发现ppp.empty()返回1,即"true",而pp容器因为有2个元素,返回0,"false"非空

 cout<<pp.size()<<"clear方法清除前容器元素个数"<<endl;
 pp.clear();
 cout<<pp.size()<<"clear方法清除后容器元素个数"<<endl;

 cin.get();
}
//5)list进一步
#include <iostream>
#include <list>    //使用list容器,必须加此头文件
using namespace std;

template<class T>
void print_list(list<T>& p,string s)
{
 list<T>::iterator iter;
 for (iter=p.begin(); iter!=p.end(); iter++)
  cout<<*iter<<" ";
 for (string::iterator siter=s.begin(); siter!=s.end(); siter++)
  cout<<*siter;
 cout<<endl;
}


void main()
{
 int ia[] = {1,2,45,6,2,3};
 list<int> p1(ia,ia+6);  //使用数组初始化list<int>容器对象
 print_list(p1,"使用数组初始化list<int>容器对象");

 list<int> p2(p1);   //使用list<int>容器对象初始化list<int>容器对象
 p2.push_front(101);
 p2.push_back(1001);
 print_list(p2,"使用list<int>容器对象初始化list<int>容器对象");

 list<int> p3;
 p3 = p2;     //直接赋值
 print_list(p3,"直接赋值");  

 list<int>::iterator iter = p3.begin();
 p3.insert(iter,10000);  //使用迭代器在指定位置插入10000
 print_list(p3,"用迭代器在指定位置插入10000");
 iter++;      //这时iter指向p3容器的第2位置了
 p3.insert(iter,3,111); //在p3的第2个位置,连续插入3个111
 print_list(p3,"在p3的第2个位置,连续插入3个111");  

 p3.sort();    //进行排序,默认为升序
 print_list(p3,"进行排序,默认为升序");  
 p3.reverse();
 print_list(p3,"翻转容器元素,即sort和reverse方法相配合,达到了按降序排列的目的");  

 //list<int>容器p3与p2互相交换各自的值
 //常规做法,利用一个中间量来进行转换,这里直接使用一个swap就可以完成目的了
 p3.swap(p2);  
 print_list(p3,"与p2交换后的p3");
 print_list(p2,"与p3交换后的p2");

 p3.remove(1001);  //移除指定元素值为1001
 print_list(p3,"移除指定元素值为1001的p3");

 p3.erase(p3.begin(),p3.end());
 print_list(p3,"erase方法将指定区域内的容器元素全部清除");
 cout<<p3.size()<<endl;

 cin.get();
}

 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值