C++ STL笔记

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

你可能感兴趣的:(C++ STL笔记)