软件世界网 购物 网址 三丰软件 | 小说 美女秀 图库大全 游戏 笑话 | 下载 开发知识库 新闻 开发 图片素材
多播视频美女直播
↓电视,电影,美女直播,迅雷资源↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
移动开发 架构设计 编程语言 Web前端 互联网
开发杂谈 系统运维 研发管理 数据库 云计算 Android开发资料
  软件世界网 -> 编程语言 -> C++STL之ACM相关知识大全 -> 正文阅读

[编程语言]C++STL之ACM相关知识大全


vector
在STL 的头文件中定义了vector(向量容器模板类),vector容器以连续数组的方式存储元素序列,可以将vector 看作是以顺序结构实现的线性表。当我们在程序中需要使用动态数组时,vector 将会是理想的选择,vector 可以在使用过程中动态地增长存储空间。
vector 模板类需要两个模板参数,第一个参数是存储元素的数据类型,第二个参数是存储分配器的类型,其中第二个参数是可选的,如果不给出第二个参数,将使用默认的分配器。
1.定义vector 向量对象的方法:
vector<int> s;

定义一个空的vector 对象,存储的是int 类型的元素。
vector s(n);//定义一个含有n 个int 元素的vector 对象。
vector s(first, last);//定义一个vector 对象,并从由迭代器first 和last 定义的序列[first,last)中复制初值。
vector 的基本操作有:
s[i]; //直接以下标方式访问容器中的元素。
s.front(); //返回首元素。
s.back(); //返回尾元素。
s.push_back(x); //向表尾插入元素x。
s.size(); //返回表长。
s.empty(); //当表空时,返回真,否则返回假。
s.pop_back(); //删除表尾元素。
s.begin(); //返回指向首元素的随机存取迭代器。
s.end(); //返回指向尾元素的下一个位置的随机存取迭代器。
s.insert(it, x); //向迭代器it 指向的元素前插入新元素val。
s.insert(it, n, x); //向迭代器it 指向的元素前插入n 个x。
s.insert(it, first, last); //将由迭代器first 和last 所指定的序列[first, last)插入到迭代器it指向的元素前面。
s.erase(it); //删除由迭代器it 所指向的元素。
s.erase(first, last); //删除由迭代器first 和last 所指定的序列[first, last)。
s.reserve(n); //预分配缓冲空间,使存储空间至少可容纳n 个元素。
s.resize(n); //改变序列的长度,超出的元素将会被删除,如果序列需要扩展(原空间小于n),元素默认值将填满扩展出的空间。
s.resize(n, val);//改变序列的长度,超出的元素将会被删除,如果序列需要扩展(原空间小于n),将用val 填满扩展出的空间。
s.clear(); //删除容器中的所有的元素。
s.swap(v); //将s 与另一个vector 对象v 进行交换。
s.assign(first, last); //将序列替换成由迭代器first 和last 所指定的序列[first, last)。[first, last)不能是原序列中的一部分。要注意的是,resize 操作和clear 操作都是对表的有效元素进行的操作,但并不一定会改变缓冲空间的大小。。

vector 上还定义了序列之间的比较操作运算符(>, <, >=, <=, ==, !=),
可以按照字典序比较两个序列。还是来看一些示例代码。输入个数不定的一组整数,再将这组整数按倒序输出,
如下所示:
#include <iostream>
#include <vector>
using namespace std;
int main()
{
    vector<int>s;
    int x;
    while(cin>>x)
        s.push_back(x);
    for(int i=s.size()-1;i>=0;i--)
        cout<<s[i]<<" ";
    cout<<endl;
    return 0;
}

iterator
iterator(迭代器)是用于访问容器中元素的指示器,从这个意义上说,iterator(迭代器)相当于数据结构中所说的“遍历指针”,也可以把iterator(迭代器)看作是一种泛化的指针。STL 中关于iterator(迭代器)的实现是相当复杂的,这里我们暂时不去详细讨论关于iterator(迭代器)的实现和使用,而只对iterator(迭代器)做一点简单的介绍。
简单地说,STL 中有以下几类iterator(迭代器):
输入iterator(迭代器),在容器的连续区间内向前移动,可以读取容器内任意值;输出iterator(迭代器),把值写进它所指向的容器中;前向iterator(迭代器),读取队列中的值,并可以向前移动到下一位置(++p,p++);双向iterator(迭代器),读取队列中的值,并可以向前向后遍历容器;随机访问iterator(迭代器), 可以直接以下标方式对容器进行访问,vector 的iterator(迭代器)就是这种iterator(迭代器);流iterator(迭代器),可以直接输出、输入流中的值;每种STL 容器都有自己的iterator(迭代器)子类,下面先来看一段简单的示例代码:
#include <iostream>
#include <vector>
using namespace std;
int main()
{
    vector<int> s;
    for(int i=0;i<10;i++)
    {
        s.push_back(i);
    }
    for(vector<int>::iterator it=s.begin();it!=s.end();it++)
    {
        cout<<*it<<" ";
    }
    cout<<endl;
    return 0;
}

vector 的begin()和end()方法都会返回一个vector::iterator 对象,分别指向vector 的首元素位置和尾元素的下一个位置(我们可以称之为结束标志位置)。对一个iterator(迭代器)对象的使用与一个指针变量的使用极为相似,或者可以这样说,指针就是一个非常标准的iterator(迭代器)。再来看一段稍微特别一点的代码:
#include <iostream>  
#include <vector>  
using namespace std;  
main()  
{  
    vector<int> s;  
    s.push_back(1);  
    s.push_back(2);  
    s.push_back(3);  
    copy(s.begin(), s.end(), ostream_iterator<int>(cout, ""));  
    cout <<endl;  
    return 1;  
}  

这段代码中的copy 就是STL 中定义的一个模板函数,
copy(s.begin(),s.end(), ostream_iterator<int>(cout, " "));

的意思是将由s.begin()至s.end()(不含s.end())所指定的序列复制到标准输出流cout 中,用” “作为每个元素的间隔。也就是说,这句话的作用其实就是将表中的所有内容依次输出。iterator(迭代器)是STL 容器和算法之间的“胶合剂”,几乎所有的STL 算法都是通过容器的iterator(迭代器)来访问容器内容的。只有通过有效地运用iterator(迭代器),才能够有效地运用STL 强大的算法功能。
string
字符串是程序中经常要表达和处理的数据,我们通常是采用字符数组或字符指针来表示字符串。STL 为我们提供了另一种使用起来更为便捷的字符串的表达方式:string。string 类的定义在头文件中。string 类其实可以看作是一个字符的vector,vector 上的各种操作都可以适用于string,另外,string 类对象还支持字符串的拼合、转换等操作。
stack
stack 模板类的定义在头文件中。
满足先进后出原则;
stack 模板类需要两个模板参数,一个是元素类型,一个容器类型,但只有元
素类型是必要的,在不指定容器类型时,默认的容器类型为deque(双端队列)。
定义stack 对象的示例代码如下:
stack<int> s1;
stack<string> s2;

stack 的基本操作有:
入栈,如例:s.push(x);
出栈,如例:s.pop();//注意,出栈操作只是删除栈顶元素,并不返回该元素。
访问栈顶,如例:s.top();
判断栈空,如例:s.empty();,当栈空时,返回true。
访问栈中的元素个数,如例:s.size();
queue
queue 模板类的定义在头文件中。
满足先进先出原则;
stack 模板类很相似,queue 模板类也需要两个模板参数,一个是元素类型,一个容器类型,元素类型是必要的,容器类型是可选的,默认为deque 类型。
定义queue 对象的示例代码如下:
queue<int> q1;
queue<double> q2;

queue 的基本操作有:
入队,如例:q.push(x); 将x 接到队列的末端。
出队,如例:q.pop(); 弹出队列的第一个元素,注意,并不会返回被弹出元素的值。
访问队首元素,如例:q.front(),即最早被压入队列的元素。
访问队尾元素,如例:q.back(),即最后被压入队列的元素。
判断队列空,如例:q.empty(),当队列空时,返回true。
访问队列中的元素个数,如例:q.size()
根据队列性质其常用于BFS题目中;
priority_queue
在头文件中,还定义了另一个非常有用的模板类priority_queue(优先队列)。
优先队列与队列的差别在于优先队列不是按照入队的顺序出队,而是按照队列中元素的优先权顺序出队(默认为大者优先,也可以通过指定算子来指定自己的优先顺序)。
priority_queue 模板类有三个模板参数,第一个是元素类型,第二个容器类型,第三个是比较算子。其中后两个都可以省略,默认容器为vector,默认算子为less,即小的往前排,大的往后排(出队时序列尾的元素出队)。
定义priority_queue 对象的示例代码如下:
priority_queue<int> q1;
priority_queue< pair<int, int> > q2; // 注意在两个尖括号之间一定要留空格。
priority_queue<int, vector<int>, greater<int> > q3; // 定义小的先出队

priority_queue 的基本操作与queue 相同。
初学者在使用priority_queue 时,最困难的可能就是如何定义比较算子了。如果是基本数据类型,或已定义了比较运算符的类,可以直接用STL 的less算子和greater 算子——默认为使用less 算子,即小的往前排,大的先出队。
如果要定义自己的比较算子,方法有多种,这里介绍其中的一种:重载比较运算符。优先队列试图将两个元素x 和y 代入比较运算符(对less 算子,调用x
#include <iostream>  
#include <queue>  
using namespace std;  
class T  
{  
    public:  
        int x, y, z;  
        T(int a, int b, int c):x(a), y(b), z(c){}  
};  
bool operator < (const T &t1, const T &t2)  
{  
    return t1.z < t2.z; // 按照z 的顺序来决定t1 和t2 的顺序,即小的往前排,大的先出队。  
}  
int main()  
{  
    priority_queue<T> q;  
    q.push(T(4,4,3));  
    q.push(T(2,2,5));  
    q.push(T(1,5,4));  
    q.push(T(3,3,6));  
    while (!q.empty())  
    {  
        T t = q.top(); q.pop();  
        cout << t.x << " " << t.y << " " << t.z << endl;  
    }  
return 0;   
}  
/*输出结果为(注意是按照z 的顺序从大到小出队的): 
3 3 6 
2 2 5 
1 5 4 
4 4 3*/ 

再看一个按照z 的顺序从小到大出队的例子:
#include <iostream>  
#include <queue>  
using namespace std;  
class T  
{  
    public:  
        int x, y, z;  
    T(int a, int b, int c):x(a), y(b), z(c)  
    {  
    }  
};  
bool operator > (const T &t1, const T &t2)  
{  
    return t1.z > t2.z;  //即大的往前排,小的先出队。
}  
int main()  
{  
    priority_queue<T, vector<T>, greater<T> > q;  
    q.push(T(4,4,3));  
    q.push(T(2,2,5));  
    q.push(T(1,5,4));  
    q.push(T(3,3,6));  
    while (!q.empty())  
    {  
        T t = q.top(); q.pop();  
        cout << t.x << " " << t.y << " " << t.z << endl;  
    }  
    return 0;  
}  

/*输出结果为:
4 4 3
1 5 4
2 2 5
3 3 6*/

如果我们把第一个例子中的比较运算符重载为:
bool operator < (const T &t1, const T &t2)
{
    return t1.z > t2.z; // 按照z 的顺序来决定t1 和t2 的顺序,即大的往前排,小的先出队。
}

则第一个例子的程序会得到和第二个例子的程序相同的输出结果。
例题:
POJ1338-丑数
http://poj.org/problem?id=1338
#include <iostream>  
#include <queue>  
using namespace std;  
typedef pair<unsigned long int, int> node_type;  
int main( int argc, char *argv[] )  
{  
    unsigned long int result[1500];  
    priority_queue< node_type, vector<node_type>,  
    greater<node_type> > Q; 
    //优先队列的声明方式:Greater为小的先输出,less为大的先出 
    Q.push( make_pair(1, 3) );  
    for (int i=0; i<1500; i++)  
    {  
        node_type node = Q.top();  
        Q.pop();  
        switch(node.second)  
        {  
            case 3: Q.push( make_pair(node.first*2, 3) );  
            case 2: Q.push( make_pair(node.first*3, 2) );  
            case 1: Q.push( make_pair(node.first*5, 1) );  
        }  
        result[i] = node.first;  //node.first访问pair的第一个元素
    }  
    int n;  
    cin >> n;  
    while (n>0)  
    {  
        cout << result[n-1] << endl;  
        cin >> n;  
    }  
    return 0;  
}

map
在STL 的头文件中定义了模板类map 和multimap,用有序二叉树来存贮类型为
pair<const Key, T>的元素对序列。
序列中的元素以const Key部分作为标识,map 中所有元素的Key 值都必须是唯一的,multimap 则允许有重复的Key 值。可以将map 看作是由Key 标识元素的元素集合,这类容器也被称为“关联容器”,可以通过一个Key 值来快速确定一个元素,因此非常适合于需要按照Key值查找元素的容器。
map 模板类需要四个模板参数,第一个是键值类型,第二个是元素类型,第三个是比较算子,第四个是分配器类型。
其中键值类型和元素类型是必要的。map 的基本操作有:

1、定义map 对象:
map<string, int> m;

2、向map 中插入元素对,有多种方法,例如:
m[key] = value;
[key]操作是map 很有特色的操作,如果在map 中存在键值为key 的元素对,
则返回该元素对的值域部分,否则将会创建一个键值为key 的元素对,值域为默认值。
所以可以用该操作向map 中插入元素对或修改已经存在的元素对的值域
m.insert( make_pair(key, value) );

直接调用insert 方法插入元素对,insert 操作会返回一个pair,当map 中没有与key 相匹配的键值时,其first 是指向插入元素对的迭代器,其second 为true;若map 中已经存在与key 相等的键值时,其first 是指向该元素对的迭代器,second 为false。
3、查找元素对:
int i = m[key];

要注意的是,当与该键值相匹配的元素对不存在时,会创建键值为key 的元素对。
map<string, int>::iterator it = m.find(key);

如果map 中存在与key 相匹配的键值时,find 操作将返回指向该元素对的迭代器,否则,返回的迭代器等于map 的end()(参见vector 中提到的begin和end 操作)。
4、删除元素对:
m.erase(key);//删除与指定key 键值相匹配的元素对,并返回被删除的元素的个数。
m.erase(it);//删除由迭代器it 所指定的元素对,并返回指向下一个元素对的迭代器。

举个简单的例子:
#include<map>  
#include<iostream>  
using namespace std;  
typedef map<int, string, less<int> > M_TYPE;  
typedef M_TYPE::iterator M_IT;  
typedef M_TYPE::const_iterator M_CIT;  
int main()  
{  
    M_TYPE MyTestMap;  
    MyTestMap[3] = "No.3";  
    MyTestMap[5] = "No.5";  
    MyTestMap[1] = "No.1";  
    MyTestMap[2] = "No.2";  
    MyTestMap[4] = "No.4";  
    M_IT it_stop = MyTestMap.find(2);  
    cout << "MyTestMap[2] = " << it_stop->second << endl;  
    it_stop->second = "No.2 After modification";  
    cout << "MyTestMap[2] = " << it_stop->second << endl;  
    cout << "Map contents : " << endl;  
    for(M_CIT it = MyTestMap.begin(); it != MyTestMap.end();it++)  
    {  
        cout << it->second << endl;  
    }  
    return 0;  
}  
/*程序执行的输出结果为: 
MyTestMap[2] = No.2 
MyTestMap[2] = No.2 After modification 
Map contents : 
No.1 
No.2 After modification 
No.3 
No.4 
No.5*/  

insert 使用方法:
#include <iostream>  
#include <map>  
using namespace std;  
int main()  
{  
    map<string, int> m;  
    m["one"] = 1;  
    m["two"] = 2;  
    // 几种不同的insert 调用方法  
    m.insert(make_pair("three", 3));//推荐使用  
    m.insert(map<string, int>::value_type("four", 4));  
    m.insert(pair<string, int>("five", 5));  
    string key;  
    while (cin>>key)  
    {  
        map<string, int>::iterator it = m.find(key);  
        if (it==m.end())  
        {  
            cout << "No such key!" << endl;  
        }  
        else  
        {  
            cout << key << " is " << it->second << endl;  
            cout << "Erased " << m.erase(key) << endl;  
        }  
    }  
    return 0;  
} 

map的例题:
HDU1263 水果
http://acm.hdu.edu.cn/showproblem.php?pid=1263
用map关联map:
代码如下:
#include <iostream>
#include <map>
#include <string>
using namespace std;
int main()
{

    int n,m;
    cin>>n;
    while(n--)
    {
        string name,space;
        int num;
        map<string,map<string,int> > mp;
        cin>>m;
        for(int i=0;i<m;i++)
        {
            cin>>name>>space>>num;
            mp[space][name]+=num;
        }
        for(map<string,map<string,int> > ::iterator it1=mp.begin();it1!=mp.end();it1++)
        {
            cout<<it1->first<<endl;
            for(map<string,int>::iterator it2=it1->second.begin();it2!=it1->second.end();it2++)
            {

                cout<<"   "<<"|----"<<it2->first<<"("<<it2->second<<")"<<endl;
            }
        }
        if(n)cout<<endl;
    }
    return 0;
}

set
set集合容器:实现了红黑树的平衡二叉检索树的数据结构,插入元素时,它会自动调整二叉树的排列,把元素放到适当的位置,以保证每个子树根节点键值大于左子树所有节点的键值,小于右子树所有节点的键值;另外,还得保证根节点左子树的高度与右子树高度相等。
平衡二叉检索树使用中序遍历算法,检索效率高于vector、deque和list等容器,另外使用中序遍历可将键值按照从小到大遍历出来。
构造set集合主要目的是为了快速检索,不可直接去修改键值。
常见用法:
begin()    ,返回set容器的第一个元素
end()      ,返回set容器的最后一个元素
clear()    ,删除set容器中的所有的元素
empty()    ,判断set容器是否为空
max_size()   ,返回set容器可能包含的元素最大个数
size()      ,返回当前set容器中的元素个数
rbegin     ,返回的值和end()相同
rend()     ,返回的值和rbegin()相同
更多用法参见:
http://www.cnblogs.com/BeyondAnyTime/archive/2012/08/13/2636375.html
直接比较例子:
#include<iostream>  
#include<set>  
#include<string>  
using namespace std;  
int main(){  
    set<string>strset;  
    set<string>::iterator it;  
    strset.insert("cantaloupes");  
    strset.insert("apple");  
    strset.insert("orange");  
    strset.insert("banana");  
    strset.insert("grapes");  
    strset.insert("grapes");   
    for(it=strset.begin();it!=strset.end();it++){  
        cout<<*it<<" ";  
    }  
    cout<<endl;  
    return 0;  
}  

运行结果:
[img]http://img.blog.csdn.net/20160403210203591
结构体中元素比较:
#include<cstring>  
#include<set>  
using namespace std;  
struct Student
{  
  int id;  
  char name[20];  
}stu1,stu2,stu3;  

struct setCmp {    
 bool operator()(Student a,Student b) {    
  return a.id>b.id;    
 }    
};   

int main(){  
    set<Student,setCmp>mys;  
    set<Student>::iterator it;  
    stu1.id=1008;  
    strcpy(stu1.name,"zhangsan");  
    mys.insert(stu1);  

    stu2.id=1001;  
    strcpy(stu2.name,"lisi");  
    mys.insert(stu2);  

    stu3.id=1005;  
    strcpy(stu3.name,"wangwu");  
    mys.insert(stu3);  

    for(it=mys.begin();it!=mys.end();++it){  
        cout<<it->id<<" "<<it->name<<endl;  
    }  
    return 0;  
}

min_element/max_element
找出容器中的最小/最大值:
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
int main()
{
    vector<int> v;
    int n,m;
    while(cin>>n)
    {
        for(int i=0;i<n;i++)
        {
            cin>>m;
            v.push_back(m);
        }
        cout<<*max_element(v.begin(),v.end())<<" "<<*min_element(v.begin(),v.end())<<endl;
        v.clear();
    }
    return 0;
}

或是:
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
int main()
{
    vector<int> v;
    int n,m;
    while(cin>>n)
    {
        for(int i=0;i<n;i++)
        {
            cin>>m;
            v.push_back(m);
        }
        float max_num=*max_element(v.begin(),v.end());
        float min_num=*min_element(v.begin(),v.end());
        cout<<max_num<<" "<<min_num<<endl;
        v.clear();
    }
    return 0;
}

sort
对容器进行排序
#include <iostream>  
#include <vector>  
#include <algorithm>  
using namespace std;  
void Print(vector<int> &L)  
{  
    for (vector<int>::iterator it=L.begin(); it!=L.end();it++)  
    cout << *it << " ";  
    cout << endl;  
}  
int main()  
{  
    vector<int> L;  
    for (int i=0; i<5; i++)   
        L.push_back(i);  
    for (int i=9; i>=5; i--)   
        L.push_back(i);  
    Print(L);  
    sort(L.begin(), L.end());  
    Print(L);  
    sort(L.begin(), L.end(), greater<int>()); // 按降序排序  
    Print(L);  
    return 0;  
}  
/*
0 1 2 3 4 9 8 7 6 5
0 1 2 3 4 5 6 7 8 9
9 8 7 6 5 4 3 2 1 0
*/

copy
在容器间复制元素:
#include <vector>  
#include <algorithm>  
#include <iostream>  
using namespace std;  
int main()  
{  
    // 先初始化两个向量v1 和v2  
    vector <int> v1, v2;  
    for (int i=0; i<=5; i++)   
        v1.push_back(10*i);  
    for (int i=0; i<=10; i++)   
        v2.push_back(3*i);  
    cout << "v1 = ( " ;  
    for (vector <int>::iterator it=v1.begin(); it!=v1.end();it++)  
        cout << *it << " ";  
    cout << ")" << endl;  
    cout << "v2 = ( " ;  
    for (vector <int>::iterator it=v2.begin(); it!=v2.end();it++)  
        cout << *it << " ";  
    cout << ")" << endl;  
    // 将v1 的前三个元素复制到v2 的中间  
    copy(v1.begin(), v1.begin()+3, v2.begin()+4);  
    cout << "v2 with v1 insert = ( " ;  
    for (vector <int>::iterator it=v2.begin(); it!=v2.end();it++)  
        cout << *it << " ";  
    cout << ")" << endl;  
    // 在v2 内部进行复制,注意参数2 表示结束位置,结束位置不参与复制  
    copy(v2.begin()+4, v2.begin()+7, v2.begin()+2);  
    cout << "v2 with shifted insert = ( " ;  
    for (vector <int>::iterator it=v2.begin(); it!=v2.end();it++)  
    cout << *it << " ";  
    cout << ")" << endl;  
    return 0;  
}  

程序的输出结果为:
v1 = ( 0 10 20 30 40 50 )
v2 = ( 0 3 6 9 12 15 18 21 24 27 30 )
v2 with v1 insert = ( 0 3 6 9 0 10 20 21 24 27 30 )
v2 with shifted insert = ( 0 3 0 10 20 10 20 21 24 27 30 )
以上资料包括以下的博客的一些摘要,有删减,添加,侵删:
http://blog.csdn.net/xindoo/article/details/8759686
http://www.cnblogs.com/BeyondAnyTime/archive/2012/08/13/2636375.html
仅代表个人观点,欢迎交流探讨,勿喷~~~
[img]http://img.blog.csdn.net/20160403211048673
PhotoBy:WLOP
http://weibo.com/wlop
......显示全文...
    点击查看全文


上一篇文章      下一篇文章      查看所有文章
2016-04-04 00:13:46  
编程语言 最新文章
Java面试题(1)
ReactiveX序列——RxSwift
C++STL之ACM相关知识大全
c++中vector向量几种情况的总结(向量指针,
SSH框架整合demo
JAX
UVA
curl备忘(1)
C#机房重构——万事开头难(二)
OJ刷题
360图书馆 软件开发资料 文字转语音 购物精选 软件下载 美食菜谱 新闻资讯 电影视频 小游戏 Chinese Culture 股票 租车
生肖星座 三丰软件 视频 开发 短信 中国文化 网文精选 搜图网 美图 阅读网 多播 租车 短信 看图 日历 万年历 2017年12日历
2017-12-15 21:45:06
多播视频美女直播
↓电视,电影,美女直播,迅雷资源↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  软件世界网 --