STL学习指南(二)

STL学习指南

上一节我们提到了STL的一些基本的使用,本篇细说一下STL中的方法C++11中实用的用法,以及string的具体使用

再谈string

第一篇我们已将初步的认识string这个类,现在具体看一看string类的详细用法

string构造

string类中提供许多的构造方法

构造函数功能
string(s)赋值为string
string(s, beg)赋值为string下标为beg到结尾的字符串
string (s, beg, end)赋值为string下标为beg到下标为end的字符串
string(num, c)赋值string为num个’c’
string()空惨构造,string 字符串为空
#include <iostream>
#include <string>
using namespace std;
int main(){
    string st, s = "hello world";
    st = string(s);         // hello world
    st = string(s, 1);      // ello world
    st = string(s, 1 , 3);  // ell
    st = string(5, '9');    // 99999
    return 0;
}
string的输入

第一篇我们已经讲过了string的输入,本次提供了详细说明和 第三种方法

#include <iostream>
#include <string>
using namespace std;
int main(){
    string st, s = "hello world";
    //1.最常规的字符串的输入方法 遇到空格 TAB 回车分割
    cin >> st;
    //2.读一整行的字符,string版本
    getchar();
    getline(cin ,st);
    cout  << st;
    //3.C风格的输入字符串 声明char数组和输入个数
    char c[20];
   	// a  也可以使用二维数组来cin.getline(c[i], 10);
    cin.getline(c, 10);
   	// b
    //cin.get(c, 10);
    cout << c;
    return 0;
}

细谈cin.getline(c,num)getline(cin,s)

我们刚刚说了string的两种输入方式但是他们之间有什么异同呢?

相同点:都存在可选的参数,指定那个字符为输入的边界 如果不添加此参数的话 默认为’ ‘\n’, 这样就解释了回车的时候就输入了字符串

不同点:string版本的getline()不需要指定读入多少个字符的参数数值, ,即读取的字符不限定,而cin.getline()限定输入字符的数量假设声明cin.getline(c,n)的话输入的字符串就是 n - 1 原因就是它本身是C风格的输入, 在C中字符数组最后一个字符默认为\0,最后的位置被\0占用了.

具体区别开如下代码的演示

#include <iostream>
#include <string>
using namespace std;
int main(){
    string st ;
    //如果输入 , 按回车没反应的 边界为 ,
    getline(cin, st, ',');      // in : 81,60
    cout << st << endl;         // out : 81

    char c[5], c1[5], c2[5];
    cin.getline(c, 10, ',');   // in : 816,0
    cout << c << endl;          // out : 816
    getchar();


    //字符个数限制
    cin.getline(c1, 5);         // in : 816041
    cout << c1 << endl;         // out :8160
    return 0;
}
string中的函数
函数名功能
size()/length()字符串的长度
capacity()当前string包含的最大字符数
insert()插入
push_back()末尾添加字符
append()追加字符串
erase()删除字符串
replace()字符串的替换
copy()字符串的复制
swap()字符串的交换
assign()字符串的赋值
find()查找
rfind()从末尾查找
find_first_of()查找第一次出现在字符串子字符的下标
find_last_of()查找最后一次出现在字符串子字符的下标
find_first_not_of()搜索第一个不在子字符串中字符的下标
find_last_not_of()搜索最后一个不在子字符串中字符的下标
front()返回字符串首个字符
back()返回末尾字符
函数具体使用
赋值方式
#include <iostream>
#include <string>
using namespace std;
int main(){
    //最常用的赋值方式
    string s = "8160415";
    //对每个字符串的的调用
    st[6] = '3';
    cout << s << ": " << s.length()<< " " << s.capacity()  << endl;
    
    //使用构造
    string st ("hello");
    cout << st << endl;

    string t;
    //t 赋值为s下标1到4
    t.assign(s, 1, 4);
    // 长度为6 s字符串
    t.assign(6, 's');
    cout << t;
    return 0;
}
字符串的插入与拼接
#include <iostream>
#include <string>
using namespace std;
int main(){
    string s = "hell";
    //用来在尾部插入单个字符
    s.push_back('o'); // hello
    //s.insert(s.end(), 'o');
    //第五个字符串后插入
    s.insert(5, " world"); // hello world
    //第五个字符串后插入并指定字符个数为2
    s.insert(11, " and", 2); // hello world a
    cout<< s;

    //字符串的追加
    string st = "gorge";
    st.append("ous");
    st.append(3, '!');
    cout << st;

    //拼接方法
    string st1 = "gorgeous" , st2 = " and brilliant", t;
    t = st1 + st2;
    cout << t;
    return 0;
}
字符串的查找
#include <iostream>
#include <string>
using namespace std;
int main(){
    string s = "I believe whatever doesn't kill you simply makes you stranger stranger";
    //1.起始位置开始查找 返回第一次的出现的首字母下标
    cout << s.find("believe") << endl; // 6

    // 下标为4开始查找
    cout << s.find('e', 4) << endl; // 2

    //搜索最后一次出现的位置,理解为从末尾查找
    cout << s.rfind("stranger") << endl; // 62 第二个 stranger

    //查找第一次出现在字符串"wl"字符的下标
    cout << s.find_first_of("wl") << endl; // 4

    //查找最后一次出现在字符串"wl"字符的下标
    cout << s[s.find_last_of("str")] << s.find_last_of("str") <<endl; // r 69

    // 搜索第一个不在子字符串"I be"中字符的下标
    cout << s.find_first_not_of("I be") << endl; // 4

    //搜索最后一个不在子字符串"str"中字符的下标
    cout << s.find_last_not_of("str") << endl; // 68
   //如果出现没找的情况返回 string::npos
    if(s.find('za') == string::npos){
       cout << "Not Exist";
    }
    return 0;
}
字符串删除
#include <iostream>
#include <string>
using namespace std;
int main(){
    string s = "I believe ";
    //删除起始位置1到末尾
    //s.erase(s.begin() + 1);
    s.erase(1);
    //删除下标1到4
    s.erase(1, 4);
    cout << s;
    //删除所有
    s.clear();
    return 0;
}
字符串的替换
#include <iostream>
#include <string>
using namespace std;
int main(){
    string s = "turn right and go straight ", t;
    t = s.replace(5, 5, "left"); // turn left and go straight
    t = s.replace(s.begin(), s.begin() + 5, "s");// sleft and go straight
    cout << t << endl;
   //replace 常常和find一起使用替换字符串
    string s1 = "old", s2 = "mature", s3 = "The old man and the sea";
    string::size_type pos = s3.find(s1);
    if(pos != string::npos){
        s3.replace(pos, s1.size(), s2);
    }
    cout << s3 << endl;
    return 0;
}
字符串转化大小写
#include <iostream>
#include <string>
#include <algorithm>
using namespace std;
int main(){
    string s = "hello";
    //1. 使用算法中的 transform 后续会将到算法
    transform(s.begin(), s.end(), s.begin(), ::toupper);
    cout << s << endl;
    //2. 使用数组
    for(int i = 0; i < s.size(); i++){
        s[i] = tolower(s[i]);
    }
    cout << s <<endl;
    return 0;
}
字符串的遍历
#include <iostream>
#include <string>
#include <algorithm>
using namespace std;
int main(){
    string s = "hello";
    for(int i = 0; i << s.size(); i++){
        cout << s[i];
    }
    //正向迭代
    for(string::iterator it = s.begin(); it != s.end(); it++){
        cout << *it;
    }
    for(auto it = s.begin(); it != s.end(); it++){
        cout << *it;
    }
    //反向迭代
    for(string::reverse_iterator it = s.rbegin(); it != s.rend(); it++){
        cout << *it;
    }
    return 0;
}
其他

STL的具体使用

上节我们主要谈了STL中刷题中常常使用的 基本工具,本篇将STL分成三类全面讲述,分别是容器(container),迭代器(Iterator)和算法(algorithm)

  1. 容器(container):erator)。 STL容器是一些模板类,提供了多种组织数据的常用方法,例如vector(向量, 类似于数组)、list(列表,类似于链表)、deque(双向队列)、set(集合)、 map(映象)、stack(栈)、queue(队列)、priority_queue(优先队列)等等, 通过模板的参数我们可以指定容器中的元素类型。

  2. 迭代器(Iterator):迭代器是对C中的指针的一般化,用来将算法和容器联系起来。几乎所有 的STL算法都是通过迭代器来存取元素序列进行工作的,而STL中的每一个 容器也都定义了其本身所专有的迭代器,用以存取容器中的元素。

  3. 算法(algorithm):算法是一些模板函数,提供了相当多的有用算法和操作,如 for_each(遍历),stable_sort(稳定排序),search(搜索),swap(交换),copy(复制)等等。

容器
序列式容器

序列式容器就是 vector list queue这样的容器 容器中的元素是有顺序的,按位置存储

vector
  • vector中方法

    函数名功能复杂度
    size()返回向量的个数 O ( 1 ) {O(1)} O(1)
    push_back(n)在向量的末尾添加n O ( 1 ) {O(1)} O(1)
    begin()返回指向向量开头的迭代器 O ( 1 ) {O(1)} O(1)
    end()返回指向向量末尾的的后一个迭代器 O ( 1 ) {O(1)} O(1)
    insert(p, x)在向量P的位置插入x O ( n ) {O(n)} O(n)
    erase§删除向量中位置p的元素 O ( n ) {O(n)} O(n)
    clear()删除向量中所有的元素 O ( n ) {O(n)} O(n)
    pop_back()删除向量的最后一个元素 O ( 1 ) {O(1)} O(1)
    resize()给向量分配大小 O ( 1 ) {O(1)} O(1)
    front()返回首元素 O ( 1 ) {O(1)} O(1)
    back()返回尾元素 O ( 1 ) {O(1)} O(1)
    empty()判断是否为空 O ( 1 ) {O(1)} O(1)
    insert(it, n, x)向迭代器it指向的元素前插入n个x O ( n ) {O(n)} O(n)
    erase(first, last)删除由迭代器first和last所指定的序列[first, last) O ( n ) {O(n)} O(n)
    reserve(n)预分配缓冲空间,使存储空间至少可容纳n个元素 O ( n ) {O(n)} O(n)
    swap(v)将s与另一个vector对象v进行交换 O ( 1 ) {O(1)} O(1)
    assign(first, last)将序列替换成由迭代器first和last所指定的序列[first, last) O ( n ) {O(n)} O(n)
    insert(it, first, last)将由迭代器first和last所指定的序列[first, last)插入到迭代器it 指向的元素前面 O ( n ) {O(n)} O(n)
    resize(n, val)改变序列的长度,超出的元素将会被删除,如果序列需要扩展(原空间小于n), 将用val填满扩展出的空间 O ( n ) {O(n)} O(n)
  • 使用,其他一些vector使用看上一节

    #include <iostream>
    #include <vector>
    using namespace std;
    int main(){
        vector<int> v1, v2;
        for(int i = 0; i < 5; i++)
        v1.push_back(i);
        
        v1.insert(v1.begin() + 1, 2, 4); // 0 4 4 1 2 3 4
        v1.erase(v1.begin() + 1, v1.begin() + 3);// 0 1 2 3 4
        v1.insert(v1.begin(), v1.begin(), v1.end()); // 0 1 2 3 4 0 1 2 3 4
        
        for(int i = 0; i < v1.size(); i++)
        cout << v1[i] << " ";
        
        cout << endl;
        v2.assign(v1.begin(), v1.begin() + 5);
        for(int i = 0; i < v2.size(); i++) // 0 1 2 3 4
        cout << v2[i] << " ";
        
        v1.swap(v2);
        for(vector<int>::reverse_iterator rit = v1.rbegin(); rit != v1.rend(); rit++)
        cout << *rit << " "; // 4 3 2 1 0
        
    return 0;
    }
    
list

list它就是个双向链表。每一个节点的内存都是独立的

  • list中的函数

    函数功能复杂度
    size()返回大小 O ( 1 ) {O(1)} O(1)
    begin()返回指开头的迭代器 O ( 1 ) {O(1)} O(1)
    end()返回指末尾的迭代器 O ( 1 ) {O(1)} O(1)
    push_back(e)尾部插入元素 O ( 1 ) {O(1)} O(1)
    push_front(e)头部插入元素 O ( 1 ) {O(1)} O(1)
    pop_front()头部删除元素 O ( 1 ) {O(1)} O(1)
    pop_back()尾部删除元素 O ( 1 ) {O(1)} O(1)
    insert(p, x)p的位置插入x O ( 1 ) {O(1)} O(1)
    insert(it, n, x)迭代器it位置插入n个x O ( n ) {O(n)} O(n)
    clear()清楚所有 O ( n ) {O(n)} O(n)
    erase§删除p位置 O ( n ) {O(n)} O(n)
    empty()判空 O ( 1 ) {O(1)} O(1)
    sort()排序 O ( n ) {O(n)} O(n)
    rbegin()上一个元素 O ( n ) {O(n)} O(n)
    unique()删除重复重元素 O ( n ) {O(n)} O(n)
    merge(l)合并 O ( n ) {O(n)} O(n)
  • 使用

    #include <iostream>
    #include <list>
    using namespace std;
    int main(){
         //初始化长度为2
        list<int> ls(2);
        //初始化为5个4
        list<int> lst(5, 4);
        //
        list<int> ls1(ls.begin(), ls.end());
    
        list<int> l1, l2, l3;
        for(int i = 0; i < 5; i++){
            l1.push_back(i);
        }
        for(int i = 0; i < 5; i++){
            l2.push_back(i);
        }
        l1.merge(l2);
        for(list<int>::iterator it = l1.begin(); it != l1.end(); it++){
            cout << *it; //0011223344
        }
        l1.unique(); // 0 1 2 3 4
        l1.reverse();// 4 3 2 1 0
        l1.push_front(0);
        // 反向迭代
        for(list<int>::reverse_iterator rit= l1.rbegin(); rit != l1.rend(); rit++){
            cout << *rit;
        }
        return 0;
    }
    
deque

deque是双端队列

  • deque中的函数

    函数功能
    size()返回大小
    empty()判断是否为空
    begin()返回首部
    end()返回末尾
    resize(n)重新分配大小
    resize(n,val)改变序列的长度,超出的元素将会被删除,小于n 将用val填满
    push_back(e)尾部插入元素
    push_front(e)头部插入元素
    pop_back()尾部删除元素
    pop_front()头部删除元素
    front()返回队头
    back()返回队尾
    insert(p,x)p位置插入x
    insert(p, n, x)p位置插入n个x
    insert(it, first, last)将由迭代器first和last所指定的序列[first, last)插入到迭代器it 指向的元素前面
    erase§删除
    erase(begin, end)删除从begin到end位置的元素
  • 使用

    #include <iostream>
    #include <deque>
    #include <vector>
    using namespace std;
    int main(){
        deque<int> d;
        for(int i = 0; i < 5; i++){
            d.push_back(i);
        }
        d.push_front(2); // 2 0 1 2 3 4
        d.insert(d.begin(), 1);// 1 2 0 1 2 3 4
        d.insert(d.begin(), 3, 2); // 2 2 2 1 2 0 1 2 3 4
        d.insert(d.begin(), d.begin(), d.end()); // 2 2 2 1 2 0 1 2 3 4 2 2 2 1 2 0 1 2 3 4
        d.erase(d.begin(), d.begin() + 10); // 2 2 2 1 2 0 1 2 3 4
        //遍历
        for(deque<int>::iterator it = d.begin(); it != d.end(); it++){
            cout << *it << " ";
        }
        cout << endl;
        //反向迭代
        for(deque<int>::reverse_iterator it = d.rbegin(); it != d.rend(); it++){
            cout << *it << " ";
        }
        return 0;
    }
    
    
关联式容器

关联式容器按元素的值来存储 包括 set 容器是保存关键字 map是保存键值对 但是一下的set, map容器有不同的特点

关键字有序无重复

  • set
  • map

关键字有序出现重复

  • multiset
  • multimap

关键字无序无重复

  • unordered_set
  • unordered_map

关键字无序有重复

  • unordered_multiset
  • unordered_multimap

他们的主要使用方法是一致的,只是对应的特性不同,通过set, map的使用就能直到其他的使用方法,

set
  • set中的方法

    函数名功能
    clear()清空set
    end()返回指向末尾的迭代器最后一个元素的下一个
    begin()返回指向开头的迭代器
    erase(key)删除key
    find(key)搜索key返回指向key的迭代器
    insert(key)向set中插入key
    rbegin()返回的是逆向的迭代器返回最后一个
    rend()返回的是逆向的迭代器返回第一个的前一个
    lower_bound(k)返回迭代器指向不小于k
    upper_bound(k)返回迭代器指向不大于k
    count()记数出现的次数
  • 使用

    #include <iostream>
    #include <map>
    #include <set>
    using namespace std;
    int main(){
        set<int> s;
        for(int i = 0; i < 10; i++){
            s.insert(i);
        }
        cout << s.size() << endl;
    
        //找到2 - 6 之间的元素
        set<int>::iterator lower = s.lower_bound(2);
        set<int>::iterator upper = s.upper_bound(6);
        //删除2 - 6 之间的元素
        s.erase(lower, upper);
    
        set<int>::iterator p = s.find(9);
        if(p != s.end()) s.erase(p);
        else cout << "Not exist";
    
        for(set<int>::iterator it = s.begin(); it != s.end(); it++){
            cout << *it << " "; // 1 7 8
        }
        for(set<int>::reverse_iterator rit = s.rbegin(); rit != s.rend(); rit++){
            cout << *rit << " ";
        }
        s.clear();
        if(s.empty()) cout << "Empty" << endl;
        return 0;
    }
    
map
  • map中的函数

    函数名功能
    clear()清空set
    end()返回指向末尾的迭代器最后一个元素的下一个
    begin()返回指向开头的迭代器
    erase(key)删除key
    find(key)搜索key返回指向key的迭代器
    insert(key)向set中插入key
    rbegin()返回的是逆向的迭代器返回最后一个
    rend()返回的是逆向的迭代器返回第一个的前一个
    lower_bound(k)返回迭代器指向不小于k
    upper_bound(k)返回迭代器指向不大于k
    swap()两个map交换
    count()指定元素出现的次数
  • 使用

    #include <iostream>
    #include <map>
    #include <set>
    using namespace std;
    int main(){
        map<int, string> m1;
        //map的插入方法
        m1[2] = "spring";
        m1.insert(map<int, string>::value_type(3, "hi"));
        m1.insert(pair<int, string>(4, "value"));
    
    
        //遍历
        for(map<int, string>::iterator it = m1.begin(); it !=m1.end(); it++){
            cout << it->first << " "<< it->second << endl;
        }
    
        //查找key
        map<int, string>::iterator pos = m1.find(2);
        if(pos != m1.end()){
            cout << pos->first << " " << pos->second << endl;
        }else cout << "Not Exist";
    
    
        map<int, string>::iterator lower = m1.lower_bound(2);
        map<int, string>::iterator upper = m1.upper_bound(3);
        m1.erase(lower, upper);
        for(map<int, string>::iterator it = m1.begin(); it !=m1.end(); it++){
            cout << it->first << " "<< it->second << endl;
        }
    
        // 反向迭代
        for(auto rit = m1.rbegin(); rit != m1.rend(); rit++){
             cout << rit->first << " " << rit->second << endl;
        }
    
    
        m1.clear();
        return 0;
    }
    
unordered_map,unordered_set

unordered_map于map的区别就是map 会按照键值对排序,所以 它是有序的, 同理set也会按照值的大小排序, unordered就是没有进行排序的,作题的时候如果出现超时的情况就考虑使用 unordered_map, unoredered_set,它们的速度更快

注意

使用vector 、set 、 map等一系列容器时,注意begin end 的位置 begin指向的是第一个元素,而end指向的是最后一个元素的后一位, 同理,rbeginrend 如下图
在这里插入图片描述

迭代器

iterator(迭代器)是用于访问容器中元素的指示器,从这个意义上说, iterator(迭代器)相当于数据结构中所说的“遍历指针”,也可以把 iterator(迭代器)看作是一种泛化的指针,STL中关于iterator(迭代器)实现是比骄傲复杂的,这里我们不去详细 讨论关于iterator(迭代器)的实现和使用,而只对iterator(迭代器)做一 点简单的介绍。

对迭代分类

  1. 输入iterator(迭代器),在容器的连续区间内向前移动,可以读取容器内任 意值; 输出iterator(迭代器),把值写进它所指向的容器中;
  2. 输出iterator(迭代器),把值写进它所指向的容器中
  3. 前向iterator(迭代器),读取队列中的值,并可以向前移动到下一位置
  4. 双向iterator(迭代器),读取队列中的值,并可以向前向后遍历容器;
  5. 随机访问iterator(迭代器), 可以直接以下标方式对容器进行访问, vector的iterator(迭代器)就是这种iterator(迭代器)
  6. 流iterator(迭代器),可以直接输出、输入流中的值;
#include <iostream>
#include <vector>
#include <iterator>
using namespace std;
int main(){
    vector<int> v {1, 2, 3};
    /**
    vector的begin()和end()方法都会返回一个vector::iterator对象, 分别指向vector的
    首元素位置和尾元素的下一个位置(我们可以称之为结束 标志位置)。 对一个
    iterator(迭代器)对象的使用与一个指针变量的使用极为相似,或者 可以这样说,
    指针就是一个非常标准的iterator(迭代器)。
    **/
    for(vector<int>::iterator it = v.begin(); it != v.end(); it++){
        cout << *it << " ";
    }
    cout << endl;
    /**
        copy就是STL中定义的一个模板函数,copy(s.begin(), s.end(), ostream_iterator<int>(cout, " "));
    的意思是将由 s.begin()至s.end()(不含s.end())所指定的序列复制到标准输出流 cout
    中,用" "作为每个元素的间隔。也就是说,这句话的作用其实就是将表 中的所有内
    容依次输出
    **/
    copy(v.begin(), v.end(), ostream_iterator<int>(cout, " "));
    return 0;
}
算法

算法是一个非常使用的STL库 通过添加include <algorithms>使用,C++中的算法库的功能是非常丰富的,我们选择常用的具体看看algorithm中有哪些使用的方法

sort

sort这个方法在做题中常常用到,可以用来给数组或者容器排序

  • 基本的使用

    #include <iostream>
    #include <vector>
    #include <algorithm>
    using namespace std;
    int main(){
        int a[5] = {8, 1, 6, 0, 4};
        // sort默认由小到大排序
        sort(a, a + 5);
        for(int i = 0; i < 5; i++){
            cout << a[i] <<" ";
        }
        cout << endl;
        vector<int> v = {3, 1, 6, 9, 4};
        sort(v.begin(), v.end());
        for(int i = 0; i < v.size(); i++){
            cout << v[i] << " ";
        }
        return 0;
    }
    
  • 由大到小排序

    #include <iostream>
    #include <vector>
    #include <algorithm>
    using namespace std;
    //由大到小排序
    bool cmp(int a, int b){
        return a > b;
    }
    int main(){
        vector<int> v = {3, 1, 6, 9, 4};
        sort(v.begin(), v.end(), cmp);
        for(int i = 0; i < v.size(); i++){
            cout << v[i] << " ";
        }
        return 0;
    }
    
  • 比较结构体

    如果让你排序成绩名单的成绩高的排名考前,如果出现成绩相同时, 按照姓排序 ,如果出现这种情况使用sort轻松解决

    #include <iostream>
    #include <vector>
    #include <algorithm>
    using namespace std;
    struct stu{
        int score;
        string name;
    };
    bool cmp(stu a, stu b){
        return a.score == b.score ? a.name < b.name : a.score > b.score;
    }
    int main(){
        vector<stu> v;
        stu t;
        for(int i = 0; i < 3; i++){
            cin >> t.score >> t.name;
            v.push_back(t);
        }
        sort(v.begin(), v.end(), cmp);
        for(int i = 0; i < v.size(); i++){
            cout << v[i].name << " " << v[i].score << endl;
        }
        return 0;
    }
    
reverse
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
void display(vector<int> v){
    for(int i = 0; i < v.size(); i++){
        cout << v[i] << " ";
    }
    cout << endl;
}
int main(){
    vector <int> v = {8, 2, 4, 5, 7};
    sort(v.begin(), v.end());
    reverse(v.begin(), v.end());
    display(v); //8 7 5 4 2
    string s = "81604284";
    //反转字符串
    reverse(s.begin(), s.begin() + 3);  //61804284
    cout << s;
}
fill

fill用来给数组或者其他容器赋值

#include <iostream>
#include <vector>
#include <cstring>
#include <algorithm>
using namespace std;
void display(vector<int> v){
    for(int i = 0; i < v.size(); i++){
        cout << v[i] << " ";
    }
    cout << endl;
}
void display1(int* beg, int *en){
    for(; beg != en; beg++){
        cout << *beg << " ";
    }
}
int main(){
    vector <int> v(7);                  // 0 0 0 0 0 0 0
    fill(v.begin(), v.begin() + 5, 2);  // 2 2 2 2 2 0 0

    int a[10];
    //当你想给数组赋值的时候可以使用memset 但是这个方法只能赋值为 0
    memset(a, 0, sizeof(a));
    //使用fill赋值
    fill(a, a + 10, 20);
    display1(a, a + 10);

    //如果是二维数组赋值时
    int b[5][5];
    fill(b[0], b[0] + 5 * 5, 2);
    /*  2 2 2 2 2
        2 2 2 2 2
        2 2 2 2 2
        2 2 2 2 2
    */
}

注意:二维数组的赋值正确方法是fill(b[0], b[0] + 5 * 5, 2),而不是fill(b, b + 5 * 5, 2) 因为二维数组在内存里存储是线性的序列的一段从 b[0]的内存开始到 n * n的大小。

swap

swap交换数值,手动写排序时用的还挺多的

#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
int main(){
    vector <int> v{8, 2, 1, 9, 3};
    swap(v[1], v[3]);
    cout << v[1] << " " << v[3]; // 9 2
}
max

返回两个值之间的最大值

cout << min(1, 2);
min

返回两个值之间的最大值

cout << max(3, 4);
replace
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
int main(){
    vector<int> v{10 ,2, 3, 4, 2, 3, 5, 2, 2};
    replace(v.begin(), v.end(), 2, 50);
  	 //将vector中等于2的值换成50
    for(int i = 0; i < v.size(); i++) cout << v[i] << " ";// 10 50 3 4 50 3 5 50 50
    return 0;
}
find
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
int main(){
    vector<int> v{10 ,2, 3, 4, 2, 3, 5, 2, 2};
    vector<int>::iterator it;
    //查找2
    it = find(v.begin(), v.end(), 2);
    if(it != v.end()) cout << *it << endl;
    else cout << "Not Exist" << endl;
    return 0;
}
next_permutation

next_permutation就是全排列的功能,这个功能非常的实用如果在数学问题中使用全排列就直接调用这个方法,比如这道题使用next_permutation很快就解决啦

#include <iostream>
#include <algorithm>
using namespace std;
int main(){
    // 1. 全排列
    string s1 = "1234", s2 = "8160";
    do{
        cout << s1 << endl;
    }while(next_permutation(s1.begin(), s1.end()));

    // 2.全排列
    do{
        cout << s2 << endl;
    }while(prev_permutation(s2.begin(), s2.end()));

    int a[3] = {0, 1, 2};
    do{
        cout << a[0] << a[1] << a[2] << endl;
    }while(next_permutation(a, a + 3));
    return 0;
}
transform
#include <iostream>
#include <algorithm>
#include <functional> // // std::plus
using namespace std;
int op_increase(int i) { return ++i;}
int main(){
    string s ="hello";
    /**
    std::transform(first1, last1, result, op_increase);
    first1, last1两个参数表示别改变的的是区间 [begin, end)
    第三个指出变换后的结果存放的迭代器区间的首个元素的迭代器位置
    第四个参数就是 对应的操作名称
    **/
    transform(s.begin() + 1, s.end(), s.begin(), ::toupper); // ELLOo
    cout << s << endl;
    vector<int> v1, v2 {10, 20, 30, 40};
    v1.resize(v2.size());
    transform(v2.begin(), v2.end(), v1.begin(), op_increase); // v1 : 11 21 31 41


    /**
    std::transform(first1, last1, first2, result, op);
    其他参数意思一致
    first2 要进行元素变换的第二个迭代器区间的首个元素的迭代器位置,
    该区间的元素个数和第一个区间相等
    **/
    transform(v2.begin(), v2.end(), v1.begin(), v2.begin(), plus<int>()); //21 41 61 81

    return 0;
}
其他

algorithm中包含许多其他功能的函数平时做题可能有的不是太多,具体使用可以参考官方文档

突然想起来,还有一个做题时用到的求gcd的方法

#include <iostream>
using namespace std;
int gcd(int a, int b){
    return b == 0 ? a : gcd(b, a % b);
}
int main(){
    int a = 25, b = 50;
    cout << gcd(a, b) << endl;
    cout << __gcd(a, b) << endl;
}

C++11中常用的特性

C++11中添加 的实用的特性,做题时用的很多

1.to_string
    int a;
    cin >> a;
	//包含在string类中
	//将int类型转化为string类型
    string s = to_string(a);
    cout << s;
2.auto的实用

刚刚在使用容器的时候都可以使用auto 进行遍历 简化写法

#include <iostream>
#include <cstdio>
#include <set>
using namespace std;
int main(){
    set<int> s;
    s.insert(1);
    s.insert(2);
    //通过迭代器的方式进行遍历
    for(set<int>::iterator it = s.begin(); it != s.end(); it++){
        cout << *it;
    }
    // 实用auto的方式就是替代了迭代器中的类型声明,简化了写法
    for(auto it = s.begin(); it != s.end(); it++){
        cout << *it;
    }
    return 0;
}
3.基于范围的for循环
#include <iostream>
#include <cstdio>
#include <set>
using namespace std;
int main(){
    set<int> s;
    s.insert(1);
    s.insert(2);
   //foreach
    for(auto its : s){
        cout << its;
    }
   //在数组中的使用方法
    int a[5] = {8, 1, 6, 3, 2};
   //遍历的元素的类型 别名 :  被遍历数组的名称
    for(int i : a){
        cout << i << " ";
 	 }
   //通过引用的方法可以改变数组中的值
    for(int &i : a){
        i *= 2;
    }
    return 0;
}

这种for循环通过不仅仅适用于数组,它也适用于STL中的容器,例如set map,使用C++ 11 中的auto,大大简化了容器的遍历写法.

4.stoi的使用

stoi的意思就是,string转化为int类型 ,类似于C中的 atoi, 同理还有

  1. stod ——string to double
  2. stof——string to float
  3. stold——string to float double
  4. stol——string to long
  5. stoll——string to long long
  6. stoul——string to unsigned long
  7. stoull——string to unsigned long long

以上都是string类中的方法,string类看一会详细说道

#include <iostream>
#include <string>
using namespace std;
int main(){
    string s = "008160";
    int a = stoi(s);
    cout << a; // 8160
    string st = "1.32";
    double b = stod(st);
    cout << b; // 1.32
    return 0;
}

注意 :stoi转化存在非法输入时, 例如 stoi("0081.60")

  1. 截取前边的数字, 知道遇到的不是数字
  2. 如果前边不是数字,那么运行时出现错误

如果stod出现非法输入时,

  1. 自动截取去前面的浮点数,直到遇到的不满足浮点数为止
  2. 如果最前面是小数点,会自动转化前面添加0
  3. 如果前面不是数字或者小数点,那么运行时出现错误

总结

把学的STL知识总结了一遍,还有不足的地方就日后补充在第三篇吧

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值