STL 标准模板库

STL意义:在数据结构和算法方面建立一套标准,提高代码复用性。

STL广义分类:容器 算法 迭代器

                        容器和算法通过迭代器进行无缝连接

STL几乎所有代码都采用模板类或模板函数

STL六大组件:

容器:将各种常用的数据结构实现出来,用来存放数据 vector\list\deque\set\map...

           常用数据结构:数组、链表、树、栈、队列、集合、映射表...

           序列式容器:强调值的排序,每个元素均有固定的位置

           关联式容器:二叉树结构,各元素之间没有严格的顺序关系

算法 Algorithms

            质变算法:运算过程中会更改区间内元素的内容 eg 拷贝、删除

            非质变算法:运算过程中不会更改区间内元素的内容 eg 查找、计数

迭代器:容器与算法之间的胶合剂。提供一种方法,其能够依序访问某容器所含各个元素,同时                   无需暴露容器内部表示方式。

             1. 算法要通过迭代器才可以访问容器中元素

             2.每个容器都有自己专属的迭代器

             3.迭代器行为类似指针,初学时可暂理解为指针

仿函数:重载() 协助算法

适配器:修饰容器、仿函数、迭代器的接口

空间配置器:空间配置和管理

STL初识:

vector存放内置、自定义数据类型

1.vector存放内置数据类型

   #include <vector>


    //创建vector容器,可看做(整型)数组
    vector<int> v;

    //用尾插法写入两个数据
    v.push_back(10);
    v.push_back(20);

方法1: 

    vector<int>::iterator itBegin = v.begin(); //起始迭代器 指向容器中第一个元素
    vector<int>::iterator itEnd = v.end();   //结束迭代器 指向容器中最后一个元素的下一个位置
    while (itBegin != itEnd)
    {
        cout << *itBegin << endl;
        itBegin++;
    }

方法2:将法1做简化

 for (vector<int>::iterator it = v.begin(); it != v.end(); it++)
    {
        cout << *it << endl;
    }

方法3:利用vector内置的遍历算法 ,需要利用函数回调,即myPrint函数在for_each中使用时调用 

#include<algorithm>   //算法头文件

void myPrint(int val)   //传入容器的数据是int,因此此处也形参也为int

{

      cout<<val<<endl;


for_each(v.begin(), v.end(), myPrint); 

 2.vector存放自定义数据类型

vector<Person> v;  类似

容器嵌套容器

——类比二维数组

大容器中储存小容器,小容器中储存int类型数据

for (vector<vector<int>> ::iterator it = v.begin(); it != v.end(); it++)
    {                                       //*it 的类型是<>内的内容,即小vector容器.因此需要在内层遍历.
        for (vector<int> ::iterator vit = (*it).begin(); vit != (*it).end(); vit++)
        {                //int类型
            cout << *vit << " ";
        }
        cout << endl;
    }

String容器

本质:string是一个类。类内部封装char* 管理这个字符串 是一个char*型容器 

1.string的构造函数

   函数原型                                           意义、使用

string()                                            创建空字符串 string s1; 

string(const char* s)                       使用字符串s初始化(c风格)

                                                       const char* str = "hello world"

                                                       string s2(str);

string (const string & str)                 拷贝构造 string s3(s2) 

string(int n , char c)                         使用n个字符c初始化 string s4(10, ‘ a ') 

2.string的赋值操作 

operator= 赋值 更为常用。

函数原型

string& operator=(const char* s)                                  string s1 = "hello world"

string& operator=(const string & s)                              string s2 = s1 ;

string& operator=(char c)                                             string s3 = 'a' ;


string& assign(const char* s)                                        s4.assign("hello world")

string& assign(const char* s , int n)                              s5.assign(s4 , 5)    //把s前n个字符赋给当前                                                                                                                                                  字符串

string& assign(const string & s)                                    s6.assign(s5)         //拷贝构造

string& assign(int n , char c)                                         s7.assign(5, 'a')     //输出5个a

3.string字符串拼接 

法一 :operator+=   重载      

                                                                                string str1 = "我";

string& operator+= (const char * s)                         str1+= "爱玩游戏"        //追加多个字符

string& operator+= (const char c)                           str1 +=  ' : '                  //追加单个字符 

string& operator+= (const string & s)                      str2 = "LOL" ; str1 += str2; //连接另一个字符串   


法二:append函数

                                                                             str3 = " I "

string& append(const char* s)                             str3.append(" love ")

string& append(const char* s , int n)                   str3.append("Game abc" , 4) 

                                                                            //拼接s中前4个字符  (Game)

string& append(const string &s)                          str3.append(str2)  //s2接在str3末尾

string& append(const string &s , int pos,int n)     str3.append(str2,0,3)   

                                                                            //str2从0号位置开始接入,一共接入3个字符

4.string查找和替换 

查找:find函数/ rfind函数

int pos = s1.find(" 字符串 ")

若找到,返回第一个字符的位置; 若未找到,返回 -1 

    string s1 = "abcde";
	int pos = s1.find("de");
	if (pos == -1)
	{
		cout << "未找到该字符串" << endl;
	}
	else
	{
		cout << "该字符串于" << pos << "位置找到" << endl;
	}

 rfind:从右往左查,查到的第一个字符串的位置,返回。

替换:replace函数

s1.replace( 1 , 3 , "1111")

//从1号位置起 3个字符 替换为"1111" 

5.string字符串比较 compare函数

利用字符的ASCII码值比较

int a = s1.compare(s2);

s1 = s2               ----------------------- a = 0

s1 > s2               ----------------------- a = 1

s1 < s2               ----------------------- a = -1

 6.string字符存取         [] 或 at =函数

读:           读取单个字符

    string s1 = "abcde";
    for (int i = 0; i < s1.size(); i++)
    {
        cout << s1[i] << " ";
        cout << endl;
    }
    for (int i = 0; i < s1.size(); i++)
    {
        cout << s1.at(i) << " ";
        cout << endl;
    }

写:              修改单个字符

    s1[0] = 'x';
    s1.at(1) = 'x'; 

7.string插入和删除 

插入 insert函数

删除 erase函数

string s1 = "abcde";
    s1.insert(1,"111");              //从1号位置开始 , 插入“111”
    //a111bcde
    cout << s1; 
    s1.erase(1, 3);                   //从1号位置开始,删除3个字符
    //abcde
    cout << s1;

8.string子串 

    string s1 = "abcde";
    string subStr = s1.substr(1,3);         //从1号位置开始,截取3个字符
    //bcd
    cout << subStr;

实用操作:获取有效信息

//从邮箱截取姓名

void getName()
{
    string str1 = " zhangsan@163.com";
    int pos = str1.find("@");
    string usrName = str1.substr(0, pos);
    cout << "姓名为" << usrName;

Vector容器 

1.基本概念:

和数组非常相似,也称为单端数组(在数组尾端添加/删除)

与数组区别:数组是静态空间,不能扩容,而vector可以动态扩展

                      动态扩展:找到更大的内存空间,将原数据拷贝到新空间,然后释放原空间。

 2.vector构造函数

创建vector容器,可以赋初值

//无参构造    

    vector<int> v1;
    for (int i = 0; i < 10; i++)
    {
        v1.push_back(i);
    }


//将区间[ v1.begin() , v1.end() ) 传入v2
    vector<int> v2(v1.begin() , v1.end());


//传入10个100
    vector<int> v3(10,100);


//拷贝构造
    vector<int> v4(v3);

3.vector赋值操作 

等号赋值

  vector<int>v1 = v0;


assign赋值

    //区间 [ v0.begin(), v0.end() ) 赋值
    vector<int>v2;
    v2.assign(v0.begin(), v0.end());

    //n个 element 赋值
    vector<int>v3;
    v3.assign(10, 100);

4.vector容量和大小

empty()     判断容器是否为空   返回true/false

capacity()  容器容量  返回int

size()         返回容器中元素的个数(<= 容量)

resize()

resize()

//重新指定容器大小

v1.resize( 10 )           //如果重新指定的比原来要长,默认用0填充新的位置,此时vector发生                                    动态扩展,新的容量会比10更大一点

v1.resize( 10,100)                       // 利用参数2可以指定填充新位置的数字,从0变为100

v1.resize( 1 )            //如果重新指定的比原来要短,多余的会被删除,size变小,容量不变

5.vector插入和删除

push_back(ele)                                                         尾插元素ele

insert(const_interator pos , ele)                                迭代器指向位置pos插入元素ele

insert(const_interator pos ,int count  ,  ele)              迭代器指向位置pos插入count个元素ele


pop_back(ele)                                                           尾删元素ele

erase(const_interator pos)                                        删除迭代器指向位置的元素

erase(const_interator start ,  const_interator end)    删除迭代器从start到end之间的元素

clear()                                                                        删除容器中所有元素

6.vector数据存取

v0[1]          返回第1号元素
v0.at(1)      返回第1号元素

v0.front()   返回容器第一个元素(第0号)

v0.back()   返回容器最后一个元素

7.vector互换容器

实现两个容器互换        swap函数

v2.swap(v1)

实际用途:收缩内存空间

当我们resize容器后,size会变小但capacity不会,造成内存的浪费。

创建匿名对象x ,将v1拷贝到x上,此时的v1.size()为2,因此x只会开辟很小的容量。

swap后,v1的容量变为小容量,而匿名对象x在本行代码执行结束后销毁。

vector<int> v1;
    for (int i = 0; i < 10000; i++)
    {
        v1.push_back(i);
    }
    cout << "v1容量为" << v1.capacity() << endl;  //12138
    cout << "v1大小为" << v1.size() << endl;        //10000
    v1.resize(2);

    //匿名对象
    vector<int>(v1).swap(v1);  
    cout << "v1容量为" << v1.capacity() << endl;  //2
    cout << "v1大小为" << v1.size() << endl;        //2

8.vector预留空间

reserve(int len)

当插入数据比较大时,vector会随着数据插入不断做动态扩展。利用reserve可以提前预留空间,减少动态扩展次数。

vector<int> v1;
    int* p = NULL;
    int num = 0;
    for (int i = 0; i < 10000; i++)
    {
        v1.push_back(i);
        if (p != &v1[0])            //利用动态扩展会找一块新的内存空间的特性,统计动态扩展次数
        {
            p = &v1[0];
                num++;
        }
    }
    cout << num;                // 24

提前预留空间后,动态扩展只有初始的1次.

v1.reserve(10000);

cout<<num;             // 1  


Deque容器 

双端数组,可以对头端进行插入删除操作

Deque与Vector: 

                         1.Deque对于头部插入删除的效率高、速度快;

                         2.Deque访问元素时速度比Vector慢,与二者内部实现有关。Deque容器由中控器                              和缓冲区组成,中控器记录不同缓冲区的地址,当现有缓冲区被数据占满时,中                              控器指向新的地址,开辟缓冲区,继续储存数据。

1.deque构造函数

deque<int> d1;

deque<int>d2(d1.begin(),d1.end());

deque<int>d3(10,100);

deque<int>d4(d3);

2.deque赋值

d2 = d1;

d3.assign(d1.begin(),d1.end());

d4.assign(10,100);

3.deque大小操作

d1.empty()

d1.size()

d1.resize(num)             //若容器变短辟,默认0填充新位置

d1.resize(num, elem)   //若容器变长,以elem填充新位置

//deque没有容量的概念

4.deque插入和删除

两端操作:

push_back(num)  //尾插

push_front(num)  //头插

pop_back()          //尾删

pop_front()          //头删

指定位置操作:

//用insert要提供迭代器

insert(pos , elem)        //在pos位置插入一个elem元素的拷贝,返回新数据的位置

insert(pos , n , elem)   // 在pos位置插入n个elem元素的拷贝,无返回值

insert(pos , beg , end) // 在pos位置插入区间[beg , end )的数据,无返回值

clear() //清空

erase(beg,end)           //删除区间数据,返回下一个数据的位置

erase(pos)                  //删除位置上数据,返回下一个数据的位置

5.deque数据存取

d1[int ]        //访问第i个元素

d1.at( int )

front()  //返回第一个元素

back()

6.deque排序操作

#include<algorithm>

sort(d.begin(),d.end())

默认排序规则:从小到大升序排列

对于支持随机访问的迭代器的容器,都可以用sort算法直接进行排序(如vector)

stack容器

特点:只有一个出口,先进的后出。

          栈底密封,栈顶开口,从栈顶进出。

          不允许有遍历行为,因为除栈顶处之外的元素外界 访问不到。

类比:挤地铁、弹匣

入栈 push              出栈 pop

stack的常用接口:

push(elem)  入栈

pop()            栈顶元素出栈

empty()        是否为空

size()            栈的大小

queue容器

STL 标准模板库

入队 push

出队 pop

返回队头元素 front

返回队尾元素 back

判断是否为空 empty

返回队列大小 size

list容器   链表

链表由一系列结点组成,而结点由数据域和指针域组成。

数据域储存本结点处元素,指针域储存下一个结点数据的地址。

通过指针实现元素之间的逻辑顺序

STL 标准模板库

STL 标准模板库

 list的优点:

                    动态存储分配,不会造成内存浪费和溢出。(用多少开多少)

                    执行插入和删除操作很方便,修改指针即可,不需移动大量元素。

list的缺点: 需要的内存空间大,遍历所需的时间长。

list和vector是两个重要的容器,他们的优缺点是互补的。

1.list构造函数

    list<int>l1;
    l1.push_back(10);
    l1.push_back(20);



    list<int>l2(l1.begin(), l1.end());


//拷贝构造
    list<int>l3(l2);


//10个1000 


    list<int>l4(10, 1000);

2.list赋值和交换 

//operator=

L2 = L1;

//assign

L2.assign(L1.begin(),L1.end());

L3.assign(10,100);  //赋值:10个100

swap

L1.swap(L2); 

3.list大小操作

//和vector相同

size()

empty()

resize(num)

resize(num,elem) 

4.list插入和删除

与之前相同:

push_back(num)  //尾插

push_front(num)  //头插

pop_back()          //尾删

pop_front()          //头删

insert(pos , elem)        //在pos位置插入一个elem元素的拷贝,返回新数据的位置

insert(pos , n , elem)   // 在pos位置插入n个elem元素的拷贝,无返回值

insert(pos , beg , end) // 在pos位置插入区间[beg , end )的数据,无返回值

clear()                         //清空

erase(beg,end)           //删除区间数据,返回下一个数据的位置

erase(pos)                  //删除位置上数据,返回下一个数据的位置

新增:

remove(elem)      //删除容器中所有与elem值匹配的元素 

5.list数据存取 

与vector不同!

( [ ] 、 at 不行 , 因为list是链表,不用连续线性空间储存数据,迭代器也不支持随机访问。)

访问第一个元素  front()

访问最后一个元素 back()

技巧:判断容器迭代器的性质

list<int>::iterator it = L1.begin(); //创建迭代器

//支持双向

it++;

it--;


//不报错-->支持随机访问;报错则不支持。(能否跳跃式访问数据)

it = it + 1; it = it + 2...

6.list反转和排序

L.reverse();         //1 2 3 4 5 ----> 5 4 3 2 1 

//所有不支持随机访问迭代器的容器,不可以用标准算法

//他们的内部会提供对应的一些算法(成员函数)

//sort(L1.begin(),L1.end())        错误

L1.sort();              //默认从小到大,升序

//改变排序方式为降序:

bool mycompare(int v2,int v2)

{

 return v1 > v2;

}

L1.sort(mycompare)

set/multiset 容器

所有元素会在插入时自动被排序

本质:属于关联式容器,底层用二叉树实现

二者区别:set不允许容器中有重复元素,而multiset允许。

1.set容器构造和赋值

set<int> s1;

set<int>s2(s1);

赋值:

s3 = s2;

2.set大小和交换 

set不提供resize

empty();

size();

s2.swap(s1);

3.set插入和删除

插入只有insert一种 

插入时会自动排序,默认升序

插入的重复值会被自动忽略

set<int>s1; 

s1.insert(10);

s1.insert(5);

s1.insert(100);

s1.insert(5);          //无效 

erase(pos)                     //删除pos位置迭代器对应的元素

erase(elem)                   //删除元素elem

clear(); erase(s.begin(),s.end())      //清空 

4.set查找和统计

查找:

set<int>::iterator pos = s1.find(30)      //查找set中有没有30,返回的是迭代器

if(pos != s1.end())                                //找到了元素,值为*pos = 30 

else                                                      //未找到

 统计:

int num = s1.count(30)                //返回容器中30的个数

                                                   //对于set容器,值为0或1.(无重复元素)

5.pair 对组的创建

利用对组可以返回两个数据

不用包含头文件

//创建法1

pair<type1,type2> p ( 数据1,数据2)

//创建法2

pair<type1,type2> p2 = make_pair(数据1,数据2) 

//访问   

p.first ;     p.second

6.set容器排序(内置类型)

set容器默认排序规则为从小到大,利用仿函数可以改变排序规则。 

class MyCompare
{
public:
	bool operator()(int v1,int v2)
	{
		return v1 > v2;
	}
};
void test01()
{
	set<int,MyCompare>s1;
	s1.insert(10);
	s1.insert(30);
	s1.insert(20);
	for (set<int, MyCompare>::iterator it = s1.begin(); it != s1.end(); it++)
	{
		cout << *it << " ";
	}
	cout << endl;
}

7.set容器排序(自定义数据类型)

自定义数据类型放到set容器中,必须利用仿函数指定排序规则,否则编译器不知道怎么处理。

class Person
{
public:
	Person(string name, int age)
	{
		m_Name = name;
		m_Age = age;
	}
	string m_Name;
	int m_Age;
};
class ComparePerson
{
	bool operator()(const Person &p1,const Person &p2)
	{
		//按年龄降序
		return p1.m_Age > p2.m_Age;
	}
};
void test01()
{
	set<Person, ComparePerson>s1;
	Person p1("张三", 18);
	Person p1("李四", 100);
	Person p1("王五", 90);
	for (set<Person, ComparePerson>::iterator it = s1.begin(); it != s1.end(); it++)
	{
		cout << (*it).m_Age << " " << (*it).m_Name << endl;
	}
}

map/multimap容器(重要)

简介:

map中所有元素都是pair(对组)

pair中第一个元素为key,索引作用;第二个元素为value,实值

所有的元素会按 键值key自动排序(升序)

本质:属于关联式容器,底层结构由二叉树实现

优点:能根据key值快速找到value值

map与multimap:map不允许容器中有重复的key值元素

                            multimap允许容器中有重复key值元素

                            二者都允许重复的value值

1.map构造和赋值

默认构造

插入数据时要插入对组pair,因为map容器中存放的元素是对组

    map<int, int>m1;
	m1.insert(pair<int,int>(1, 10));
	m1.insert(pair<int, int>(3, 30));
	m1.insert(pair<int, int>(2, 20));
	for (map<int, int>::iterator it = m1.begin(); it != m1.end(); it++)
	{
		cout << (*it).first << " " << it->second << endl;
	}

拷贝构造

map<int,int>m2(m1);

赋值

map<int,int>m3;

m3 = m2;

 2.map大小和交换

size();

empty();

swap(m);

3.map插入和删除

插入

m.insert(pair<int,int>(1,10));

m.insert(make_pair(2,20));

m[3] = 30;                           //不建议插数时使用,推荐在访问已有键值对时使用

删除

erase(pos)                 //pos是迭代器

erase(key);                //按照key删除! 

erase(beg,end)         // 等价于clear()

4.map查找和统计 

find(key)                         //若找到,返回key所在位置迭代器;若未找到,返回end()

map<int, int>::iterator pos = m1.find(3);
if(pos != m.end())            //找到了,key为(*pos).first; value为pos->second
else                          //没找到

count(key)                      //统计指定key的个数 ,返回整数

                                      // map,0或1; multimap可能大于1

5.map排序 

默认排序是按key值从小到大,利用仿函数改变排序规则

class MyCompare
{
public:
	bool operator()(int v1, int v2)
	{
		return v1 > v2;
	}
};
void test01()
{
	map<int, int,MyCompare>m1;
	m1.insert(make_pair(1, 10));
	m1.insert(make_pair(2, 20));
	for (map<int, int,MyCompare>::iterator it = m1.begin(); it != m1.end(); it++)
	{
		cout << (*it).first << " " << it->second << endl;
	}
	
}

案例tips

1. 前面创建好迭代器it,后面for循环使用it时,第一个参数不用填写。

2.可以用count和index来遍历部分容器,减少运算。

    multimap<int,Worker>::iterator it = m.find(0);
    int index = 0;
	int count = m.count(0);
	for (; it != m.end() && index < count; it++, index++)
	{
		cout << it->second.m_Name << " " << it->second.m_Salary << endl;
	}

3.用下面这种向函数传入两个容器的方式,可以在遍历A容器的同时给B容器传值(*it)

void setWorker(vector<Worker> &v, multimap<int, Worker>& m)
{
	for (vector<Worker>::iterator it = v.begin(); it != v.end(); it++)
	{
		int deptNum = rand() % 3;
		//将员工插入分组
		m.insert(make_pair(deptNum, *it));
	}
}



函数对象(仿函数)

1.函数对象使用时,可以像普通函数一样调用。可以有参数和返回值。

class MyAdd
{
public:
	int operator()(int v1, int v2)
	{
		return v1 + v2;
	}
};
void test01()
{
	MyAdd ad;
	cout<<ad(10, 20);
}

2.函数对象可以有属于自己的状态

仿函数写在类中,因此可以通过创建类内的变量来描述函数对象的状态。下面例子中,用count记录函数对象调用的次数。

class MyPrint
{
public:
	MyPrint()
	{
		count = 0;
	}
	void operator()(string text)
	{
		cout << text << endl;
		count++;
	}
	int count;
};
void test01()
{
	MyPrint mp;
	mp("Hello World");
	mp("Hello World");
	mp("Hello World");
	cout << mp.count << endl;
}

3.函数对象可以作为参数传递

class MyPrint
{
public:
	void operator()(string text)
	{
		cout << text << endl;
	}
};
void doPrint(MyPrint& mp, string text)
{
	mp(text);
}

谓词

概念:返回bool类型的仿函数

若operator() 接收一个参数,称为一元谓词;接收两个参数,称为二元谓词。

一元谓词:

class GreaterThanFive
{
public:
	bool operator()(int a)
	{
		return a > 5;
	}
};
void test01()
{
	vector<int>v;
	for (int i = 0; i < 10; i++)
	{
		v.push_back(i);
	}
	                                                       //匿名对象
	vector<int>::iterator it = find_if(v.begin(), v.end(), GreaterThanFive());
	if (it != v.end())
	{
		cout << "找到了,值为" << *it;
	}
	else
		cout << "未找到" << endl;
}

内建函数对象

C++内部别人写好的仿函数,可以直接用。

包含头文件:#include<functional>

1.算数仿函数

negate  取反仿函数

negate<int>p;

p(50);                //-50

plus 加法仿函数

plus<int>p;       //二元的也只需传入一个int,因为默认相加二者类型相同

p(10,20);          //30 

minus 减法

multiples 乘法

divides 除法

modulus 取模 

2.关系仿函数 

上文实现了改变sort函数排序规则:

class MyCompare
{
public:
	bool operator()(int v1, int v2)
	{
		return v1 > v2;
	}
};
sort(v.begin(),v.end(),MyCompare())

而利用内置关系仿函数greater,可以快速实现,不用自己写仿函数。

sort(v.begin(),v.end(),greater<int>())

其他关系仿函数:(不常用)

bool equal_to<T>           //等于                                           equal_to<int>()

bool not_equal_to<T>

bool greater_equal<T> //大于等于

bool less<T>

bool less_equal<T>

3.逻辑仿函数(开发中几乎用不到)

bool logical_and<T> ()      //与

bool logical_or<T> ()         //或

bool logical_not<T>  ()      //非



STL常用算法

1.遍历

for_each

for_each(v.begin(),v.end(),print01)              //普通函数

for_each(v.begin(),v.end(),print02())           //仿函数

transform  搬运容器到另一个容器中

a.  搬运前要先给目标容器开辟空间

b.  _Func可以是仿函数也可以是普通函数,其意义在于可以实现搬运同时修改数据

    v2.resize(v1.size());
    transform(v1.begin(), v1.end(), v2.begin(), _Func);

2.查找 

find 查找指定元素,找到返回指定元素迭代器,找不到返回结束迭代器

find(iterator beg,iterator end,value)

注意:查找自定义类型数据时,需要在类内重载==(如下)

bool operator==(const Person&p)
{
   if(//.............)
     {
          return true;
     }
}

find_if 按条件查找元素

find_if(iterator beg,iterator end, _Pred)                  //_Pred 函数或者谓词,作为条件

class GreaterThanFive
{
public:
	bool operator()(int a)
	{
		return a > 5;
	}
};

vector<int>::iterator it = find_if(v.begin(),v.end(),GreaterThanFive())

注意:查找自定义类型数据时,需要在类内重载== 

adjacent_find 查找相邻且重复元素

adjacent_find(iterator begin,iterator end)

若找到,返回第一个元素的迭代器;若未找到,返回end()

binary_search 查找指定元素是否存在

bool binary_search(iterator beg,iterator end,value)

查到,返回TRUE;否则返回FALSE

容器必须是有序序列(底层用二叉树实现)

count 统计元素个数

count(iterator beg,iterator end,value)

返回元素个数 int类型

统计自定义类型时,重载==(转到定义,可以明白原理)

count_if 按条件统计元素个数

count_if(iterator begin,iterator end, _Pred)                              _Pred 函数或谓词 作为条件

返回元素个数 int类型

3.排序 

sort  普通排序

sort(iterator begin,iterator end)   或  sort(iterator begin,iterator end , _Pred)

不填谓词,默认从小到大排序。

random_shuffle 洗牌 指定范围内元素随即调整顺序

random_shuffle(iterator begin,iterator end)

使用时,加入随机数种子,变为真随机。srand((unsigned int)time(NULL))

merge 两个容器元素合并,并存储到另一个容器中

merge(iterator beg1,iterator end1,iterator beg2,iterator end2, iterator dest)   

                                                                                               //最后一个参数是目标容器起始迭代器

两个待合并容器必须是有序的,合并后的容器也将是有序的。

需要提前给目标容器分配空间  v.resize(v1.size() + v2.size())

reverse 将容器内元素反转

reverse(iterator beg,iterator end)              1 2 3 4 5 ------------> 5 4 3 2 1

4. 拷贝和替换

copy 将元素拷贝到另一个容器中

copy(iterator beg,iterator end,iterator dest)

另一个容器也要提前分配空间 v2.resize(v1,size())

replace 指定范围内所有旧元素替换为新元素

replace(iterator beg,iterator end , oldvalue , newvalue)

replace_if 区间范围内满足条件的元素替换为新元素

replace(iterator beg,iterator end , _Pred , newvalue)

swap 互换两个容器的元素

同种类型容器

swap(容器1,容器2)

5.算数生成算法   #include<numeric>

accumulate 计算容器中数据之和

accumulate(iterator beg, iterator end ,  num)                   //num是起始累加值

fill 向容器中填充指定元素

fill( iterator beg,iterator end , num)                                  //num为填充值

6.集合算法

set_intersection 求两个容器的交集

两个集合必须是有序序列

提前给目标容器开辟空间 考虑极限情况: vTarget.resize(min(v1.size(),v2.size()))

vector<int>::iterator itEnd = set_intersection(v1.begin(),v1.end(),v2.begin(),v2.end(),vTarget.begin())

返回值是交集结束位置迭代器,用itEnd接收。

遍历时:for_each(vTarget.begin() , itEnd , myPrint()) 若用vTarget.end() 则后面可能会有若干个0

set_union 求两个容器并集

两个集合必须是有序序列

提前给目标容器开辟空间 考虑极限情况: vTarget.resize(v1.size() + v2.size())

vector<int>::iterator itEnd =

set_union(v1.begin(),v1.end(),v2.begin(),v2.end(),vTarget.begin())

返回值是并集结束位置迭代器,用itEnd接收。

遍历时:for_each(vTarget.begin() , itEnd , myPrint()) 若用vTarget.end() 则后面可能会有若干个0

set_difference 求两个容器差集 

V1和V2的差集:V1中和V2不相交的部分

V2和V1的差集:V2中和V1不相交的部分

提前给目标容器开辟空间 考虑极限情况: vTarget.resize(max ( v1.size() , v2.size() ) )

vector<int>::iterator itEnd =

set_difference(v1.begin(),v1.end(),v2.begin(),v2.end(),vTarget.begin())

返回值是差集 结束位置迭代器,用itEnd接收。

上一篇:QT Map移除元素(前n个)


下一篇:14Cr1MoR-14Cr1MoR的力学性能