C++课程学习笔记第九周(下):STL(下)

注:该课程大纲详见 https://www.cnblogs.com/inchbyinch/p/12398921.html

1 关联容器

1.1 multiset

//multiset类模板
template<class Key, class Pred = less<Key>, class A = allocator<Key> >
class multiset { …… };

Pred类型的变量决定了multiset中的元素,“一个比另一个小”是怎么定义的。multiset运行过程中,比较两个元素x,y的大小的做法,就是生成一个Pred类型的变量,假定为op,若表达式op(x,y) 返回值为true,则x比y小。由于less函数模板是通过<来比较的,因此默认情况下自己的类Key需要实现运算符<的重载。

multiset的成员函数

  • iterator find(const T & val); 在容器中查找值为val的元素,返回其迭代器(x小于y和y小于x同时为false即为相等)。如果找不到,返回end()。
  • iterator insert(const T & val); 将val插入到容器中并返回其迭代器。
  • void insert(iterator first, iterator last); 将区间(前闭后开)插入容器。
  • int count(const T & val); 统计有多少个元素的值和val相等。
  • iterator lower_bound(const T & val); 查找一个最大的位置it,使得begin()到it(前闭后开)中所有的元素都比val小。
  • iterator upper_bound(const T & val); 查找一个最小的位置it,使得it到end()(前闭后开)中所有的元素都比val大。
  • pair<iterator,iterator> equal_range(const T & val); 同时求得lower_bound和upper_bound。
  • iterator erase(iterator it); 删除it指向的元素,返回其后面的元素的迭代器(Visual studio 2010上如此,但是在C++标准和Dev C++中,返回值不是这样),也可以删除指定值。
//示例:multiset使用
#include <iostream>
#include <set> //使用multiset须包含此文件
using namespace std;
template <class T>
void Print(T first, T last){ 
    for(;first != last; ++first) cout << * first << " ";
    cout << endl;
}
class A {
    int n;
public:
    A(int n_ ) { n = n_; }
    friend bool operator < ( const A & a1, const A & a2 ) { return a1.n < a2.n; }
    friend ostream& operator<< ( ostream & o, const A & a2 ) { o << a2.n; return o; }
    friend class MyLess;
};
struct MyLess {
    bool operator()( const A & a1, const A & a2){ //按个位数比大小 
        return ( a1.n % 10 ) < (a2.n % 10); 
     }
};
typedef multiset<A> MSET1; //MSET1用 "<"比较大小
typedef multiset<A, MyLess> MSET2; //MSET2用 MyLess::operator()比较大小

int main(){
    const int SIZE = 6;
    A a[SIZE] = { 4,22,19,8,33,40 };
    MSET1 m1;
    m1.insert(a, a+SIZE);
    m1.insert(22);
    cout << "1) " << m1.count(22) << endl; //输出 1) 2
    cout << "2) "; Print(m1.begin(),m1.end()); //输出 2) 4 8 19 22 22 33 40
    //m1元素:4 8 19 22 22 33 40
    MSET1::iterator pp = m1.find(19);
    if( pp != m1.end() ) //条件为真说明找到
        cout << "found" << endl; //本行会被执行,输出 found
    cout << "3) "; cout << * m1.lower_bound(22) << ","
        <<* m1.upper_bound(22)<< endl; //输出 3) 22,33
    pp = m1.erase(m1.lower_bound(22), m1.upper_bound(22));
    //pp指向被删元素的下一个元素
    cout << "4) "; Print(m1.begin(),m1.end()); //输出 4) 4 8 19 33 40
    cout << "5) "; cout << * pp << endl; //输出 5) 33
    MSET2 m2; // m2里的元素按n的个位数从小到大排
    m2.insert(a,a+SIZE);
    cout << "6) "; Print(m2.begin(),m2.end()); //输出 6) 40 22 33 4 8 19
    return 0;
}    
    

1.2 set

不允许重复元素。插入set中已有的元素时,则忽略插入,且返回的 pair< iter, bool >中bool为false。

//set类模板
template<class Key, class Pred = less<Key>, class A = allocator<Key> >
class set { … }

//示例
#include <iostream>
#include <set>
using namespace std;

int main() {
    typedef set<int>::iterator IT;
    int a[5] = { 3,4,6,1,2 };
    set<int> st(a, a+5); // st里是 1 2 3 4 6
    pair< IT, bool > result; //pair定义可见multimap一节
    result = st.insert(5); // st变成 1 2 3 4 5 6
    if( result.second ) //插入成功则输出被插入元素
        cout << * result.first << " inserted" << endl; //输出: 5 inserted
    if( st.insert(5).second ) 
        cout << * result.first << endl;
    else
        cout << *result.first << " already exists" << endl;//输出 5 already exists
    pair<IT,IT> bounds = st.equal_range(4);
    cout << * bounds.first << "," << * bounds.second ; //输出:4,5
    return 0;
}

1.3 multimap

  • map/multimap里放着的都是pair模版类的对象,且按first从小到大排序
  • multimap中的元素由<关键字,值>组成,每个元素是一个pair对象,关键字就是first成员变量,其类型是Key
  • multimap中允许多个元素的关键字相同。元素按照first成员变量从小到大排列,缺省情况下用 less< Key > 定义关键字的“小于”关系。
//STL中pair模板
template<class _T1, class _T2>
struct pair{
    typedef _T1 first_type;
    typedef _T2 second_type;
    _T1 first;
    _T2 second;
    pair(): first(), second() { }
    pair(const _T1& __a, const _T2& __b) : first(__a), second(__b) { }
    template<class _U1, class _U2>
    pair(const pair<_U1, _U2>& __p) : first(__p.first), second(__p.second) { }
};
//第三个构造函数用法示例:
pair<int,int> p(pair<double,double>(5.5,4.6)); //p.first=5, p.second=4


//multimap模板
template<class Key, class T, class Pred = less<Key>, class A = allocator<T> >
class multimap {
    …
    typedef pair<const Key, T> value_type;
    ……
}; //Key代表关键字的类型


//示例1:multimap用法
#include <iostream>
#include <map>
using namespace std;

int main() {
    typedef multimap<int,double,less<int> > mmid;
    mmid pairs;
    cout << "1) " << pairs.count(15) << endl;
    pairs.insert(mmid::value_type(15,2.7));//typedef pair<const Key, T> value_type;
    pairs.insert(mmid::value_type(15,99.3));
    cout << "2) " << pairs.count(15) << endl; //求关键字等于某值的元素个数 2
    pairs.insert(mmid::value_type(30,111.11));
    pairs.insert(mmid::value_type(10,22.22));
    pairs.insert(mmid::value_type(25,33.333));
    pairs.insert(mmid::value_type(20,9.3));
    for( mmid::const_iterator i = pairs.begin(); i != pairs.end(); i++ )
    cout << "(" << i->first << "," << i->second << ")" << ",";
    //(10,22.22),(15,2.7),(15,99.3),(20,9.3),(25,33.333),(30,111.11)
}


//示例2:学生成绩录入和查询系统
//接受以下两种输入: Add name id score 或者 Query score
//name是个字符串,中间没有空格,代表学生姓名。id是个整数,代表学号。score是个整数,表示分数。学号不会重复,分数和姓名都可能重复。两种输入交替出现。第一种输入表示要添加一个学生的信息。第二种输入表示要查询,碰到这种输入,就输出已有记录中分数比score低的最高分获得者的姓名、学号和分数。如果有多个学生都满足条件,就输出学号最大的那个学生的信息。如果找不到满足条件的学生,则输出“Nobody”
//输入样例:
Add Jack 12 78
Query 78
Query 81
Add Percy 9 81
Add Marry 8 81
Query 82
Add Tom 11 79
Query 80
Query 81
输出结果样例:
Nobody
Jack 12 78
Percy 9 81
Tom 11 79
Tom 11 79

//实现代码
struct CStudent{ //定义学生信息的类
    string name;
    int id;
    int score;
};
typedef multimap<int, CStudent> mmap;

int main(){
    string s;
    CStudent stu;
    int temp;
    mmap score_os; //定义一个成绩系统
    mmap::iterator p;

    while(cin >> s){ //读入指令
        if(s == "Add"){
            cin >> stu.name >> stu.id >> stu.score;
            score_os.insert(mmap::value_type(stu.score, stu));
            //mp.insert(make_pair(stu.score,stu)); 也可以
        }else if(s == "Query"){
            cin >> temp;
            p = score_os.lower_bound(temp);
            if(score_os.empty() || p == score_os.begin()) 
                //若字典为空或全部都不小于temp
                cout << "Nobody" << endl;
            else{ //找到小于查询值的分数
                --p; //将指针前移一位
                stu = p->second; //获取所求的学生信息
                //若指针有效且分数一样,则持续前移以查找
                while(--p!=score_os.begin() && p->first==stu.score){ 
                    if(p->second.id > stu.id)  stu = p->second;
                 }
                //刚才跳出循环可能是因为移动到开头了,需要单独处理
                if(p==score_os.begin() && p->first==stu.score){ 
                    if(p->second.id > stu.id)  stu = p->second;
                 }
                cout << stu.name << " " << stu.id << " " << stu.score << endl;
             }
        }else{
            cout << "输入有误,重新输入" << endl;
        }
    }

    return 0;
}

1.4 map

  • map 中的元素都是pair模板类对象。与multimap的唯一区别就是map中关键字(first成员变量)各不相同。元素按照关键字从小到大排列,缺省情况下用 less< Key >,即“<” 定义“小于”。
  • 若pairs为map模版类的对象,pairs[key]返回对关键字等于key的元素的值(second成员变量)的引用。若没有关键字为key的元素,则会往pairs里插入一个关键字为key的元素,其值用无参构造函数初始化,并返回其值的引用。
//模板
template<class Key, class T, class Pred = less<Key>, class A = allocator<T> >
class map {
    …
    typedef pair<const Key, T> value_type;
    …
};

//示例
template <class Key,class Value>
ostream & operator <<( ostream & o, const pair<Key,Value> & p){
    o << "(" << p.first << "," << p.second << ")";
    return o;
}

int main() {
    typedef map<int, double, less<int> > mmid;
    mmid pairs;
    cout << "1) " << pairs.count(15) << endl; //1) 0
    pairs.insert(mmid::value_type(15, 2.7));
    pairs.insert(make_pair(15,99.3)); //make_pair生成一个pair对象
    cout << "2) " << pairs.count(15) << endl; //2) 1
    pairs.insert(mmid::value_type(20,9.3));
    mmid::iterator i;
    cout << "3) ";
    for( i = pairs.begin(); i != pairs.end();i ++ ) 
        cout << * i << ",";   //3) (15,2.7),(20,9.3),
    cout << endl;
    cout << "4) ";
    int n = pairs[40];//如果没有关键字为40的元素,则插入一个
    for( i = pairs.begin(); i != pairs.end();i ++ )
        cout << * i << ",";  //4) (15,2.7),(20,9.3),(40,0),
    cout << endl;
    cout << "5) ";
    pairs[15] = 6.28; //把关键字为15的元素值改成6.28
    for( i = pairs.begin(); i != pairs.end();i ++ )
        cout << * i << ",";  //5) (15,6.28),(20,9.3),(40,0),
}

注意:C++11中提供了unordered_map和unordered_multimap,实现方式是哈希表,更好用。

2 容器适配器

  • 由于容器适配器不支持迭代器,故STL中很多算法都不适用于适配器。
  • 均有常用函数:empty、size。
//stack类模板
template<class T, class Cont = deque<T> >
class stack{ … };

//queue类模板
template<class T, class Cont = deque<T> >
class queue{ … };

//priority_queue类模板
template <class T, class Container = vector<T>, class Compare = less<T> >
class priority_queue{ … };

2.1 stack

  • 可用 vector, list, deque来实现。缺省情况下,用deque实现。用 vector和deque实现,比用list实现性能好。
  • stack 有主要操作:push、pop、top。

2.2 queue

  • 和stack 基本类似,可以用 list和deque实现。缺省情况下用deque实现。
  • queue 有主要操作:push、pop、front、back。(注意此pop是弹出头元素,与stack不同;front返回头元素引用)

2.3 priority_queue

  • 和queue类似,可以用vector和deque实现。缺省情况下用vector实现。
  • priority_queue 通常用堆排序技术实现,保证最大的元素总是在最前面。即执行pop操作时,删除的是最大的元素;执行top操作时,返回的是最大元素的常引用。默认的元素比较器是less< T >。
  • priority_queue 中top函数返回的是const型引用,如果是非const则可能有被修改成非最大值的风险。
int main(){
    priority_queue<double> pq1;
    pq1.push(3.2); pq1.push(9.8); pq1.push(9.8); pq1.push(5.4);
    while( !pq1.empty() ) {
        cout << pq1.top() << " ";
        pq1.pop();
     } //上面输出 9.8 9.8 5.4 3.2
    cout << endl;
    priority_queue<double, vector<double>, greater<double> > pq2;
    pq2.push(3.2); pq2.push(9.8); pq2.push(9.8); pq2.push(5.4);
    while( !pq2.empty() ) {
        cout << pq2.top() << " ";
        pq2.pop();
     } //上面输出 3.2 5.4 9.8 9.8
    return 0;
}    

3 算法

STL提供能在各种容器中通用的算法(大约有80多种),如插入、删除、查找、排序等。STL算法部分主要由头文件< algorithm >, < numeric >, < functional >组成。要使用 STL中的算法函数必须包含头文件< algorithm >,对于数值算法须包含< numeric >,< functional >中则定义了一些模板类,用来声明函数对象。STL中绝大部分传给函数模板的操作pred都是函数对象(其实也可以是函数指针或函数名。)

算法就是一个个函数模板,算法通过迭代器来操纵容器中的元素。许多算法可以对容器中的一个局部区间进行操作,因此需要两个参数,一个是起始元素的迭代器,一个是终止元素的后面一个元素的迭代器,比如排序和查找。有的算法返回一个迭代器。比如 find() 算法,在容器中查找一个元素,并返回一个指向该元素的迭代器。算法可以处理容器,也可以处理普通数组。

大多重载的算法都是有两个版本的,其中一个是用“==”判断元素是否相等,或用“<”来比较大小;而另一个版本多出来一个类型参数“Pred”,以及函数形参“Pred op”,该版本通过表达式“op(x,y)”的返回值是ture还是false,来判断x是否“等于”y,或者x是否“小于”y。

STL中的算法大致可以分为以下七类:

  • 1.不变序列算法
  • 2.变值算法
  • 3.删除算法
  • 4.变序算法
  • 5.排序算法
  • 6.有序区间算法
  • 7.数值算法

3.1 不变值算法

此类算法不会修改算法所作用的容器或对象,适用于所有容器。它们的时间复杂度都是O(n)的。

最常用:

  • min 求两个对象中较小的(可自定义比较器)
  • max 求两个对象中较大的(可自定义比较器)
  • min_element 求区间中的最小值(可自定义比较器)
  • max_element 求区间中的最大值(可自定义比较器)
  • for_each 对区间中的每个元素都做某种操作(不改变原值)
  • count 计算区间中等于某值的元素个数
  • count_if 计算区间中符合某种条件的元素个数
  • find 在区间中查找等于某值的元素
  • find_if 在区间中查找符合某条件的元素

其他:

  • find_end 在区间中查找另一个区间最后一次出现的位置,类似查找子序列(可自定义比较器)
  • find_first_of 在区间中查找第一个出现在另一个区间中的元素 (可自定义比较器)
  • adjacent_find 在区间中寻找第一次出现连续两个相等元素的位置(可自定义比较器)
  • search 在区间中查找另一个区间第一次出现的位置(可自定义比较器)
  • search_n 在区间中查找第一次出现等于某值的连续n个元素(可自定义比较器)
  • equal 判断两区间对应元素是否相等(可自定义比较器)
  • mismatch 逐个比较两个区间的元素,返回第一次发生不相等的两个元素的位置(可自定义比较器)
  • lexicographical_compare 按字典序比较两个区间的大小(可自定义比较器)

3.2 变值算法

最常用:

  • for_each 对区间中每一个元素进行某种操作,实现:逐个元素op(elem)。
  • copy 复制一个区间内容至另一处
  • copy_backward 从后往前复制区间内容至别处(适用于源区间和目标区间有重叠的情况)
  • transform 将区间元素进行某种操作后拷贝到别处(两种模板,可以进行一元操作或二元操作),实现:逐个元素op(elem)后赋给目标区间。注意:操作本身不改变elem值,但是可以原地赋给elem,效果就是原地进行函数变换。

其他:

  • swap_ranges 交换两个区间内容,实现:逐个元素sawp。
  • fill 将目标值逐个赋给区间元素
  • fill_n 用目标值替换区间中的n个元素,和fill的区别是用个数n代替尾迭代器。
  • generate 用某个函数调用结果填充区间,常用于随机数生成。
  • generate_n 用某个函数调用结果替换区间中的n个元素。
  • replace 将区间中的某个值替换为另一个值
  • replace_if 将区间中符合某种条件的值替换成另一个值,实现:若pred(elem)==true,则替换。
  • replace_copy 将一个区间拷贝到另一个区间,拷贝时某个值要换成新值拷过去
  • replace_copy_if 将一个区间拷贝到另一个区间,拷贝时符合某条件的值要换成新值拷过去
#include <vector>
#include <iostream>
#include <numeric>
#include <list>
#include <algorithm>
#include <iterator>
using namespace std;
class CLessThen9 {
public:
    bool operator()( int n) { return n < 9; }
};
void outputSquare(int value ) { cout << value * value << " "; }
int calculateCube(int value) { return value * value * value; }

int main() {
    const int SIZE = 10;
    int a1[] = { 1,2,3,4,5,6,7,8,9,10};
    int a2[] = { 100,2,8,1,50,3,8,9,10,2 };
    vector<int> v(a1, a1+SIZE);
    ostream_iterator<int> output(cout," "); //注意用法
    random_shuffle(v.begin(), v.end());
    cout << endl << "1) ";
    copy( v.begin(), v.end(), output);
    copy( a2, a2+SIZE, v.begin());
    cout << endl << "2)";
    cout << count(v.begin(), v.end(), 8);
    cout << endl << "3)";
    cout << count_if(v.begin(), v.end(), CLessThen9());
    cout << endl << "4)";
    cout << * (min_element(v.begin(), v.end()));
    cout << endl << "5)";
    cout << * (max_element(v.begin(), v.end()));
    cout << endl << "6) ";
    cout << accumulate(v.begin(), v.end(), 0);//求和
    cout << endl << "7) ";
    for_each(v.begin(), v.end(), outputSquare);
    vector<int> cubes(SIZE);
    transform(a1, a1+SIZE, cubes.begin(), calculateCube);
    cout << endl << "8) ";
    copy( cubes.begin(), cubes.end(), output);
}

3.3 删除算法

删除算法会删除一个容器里的某些元素。这里所说的“删除”,并不会使容器里的元素减少,其工作过程是:将所有应该被删除的元素看做空位子,然后用留下的元素从后往前移,依次去填空位子。元素往前移后,它原来的位置也就算是空位子,也应由后面的留下的元素来填上。最后,没有被填上的空位子,维持其原来的值不变。删除算法不应作用于关联容器。

  • unique 删除区间中连续相等的元素,只留下一个(可自定义比较器),返回删除后的区间的最后一个元素的后一个迭代器,可以用其与begin比较来获取有效长度。
  • unique_copy 拷贝区间到另一个区间。连续相等的元素,只拷贝第一个到目标区间 (可自定义比较器)
  • remove 删除区间中等于某个值的元素
  • remove_if 删除区间中满足某种条件的元素
  • remove_copy 拷贝区间到另一个区间。等于某个值的元素不拷贝
  • remove_copy_if 拷贝区间到另一个区间。符合某种条件的元素不拷贝
int main(){
    int a[5] = { 1,2,3,2,5};
    int b[6] = { 1,2,3,2,5,6};
    ostream_iterator<int> oit(cout,",");
    int * p = remove(a,a+5,2);
    cout << "1) "; copy(a,a+5,oit); cout << endl;
    //输出 1) 1,3,5,2,5,
    cout << "2) " << p - a << endl; //输出 2) 3
    vector<int> v(b,b+6);
    remove(v.begin(),v.end(),2);
    cout << "3) ";copy(v.begin(),v.end(),oit);cout << endl;
    //输出 3) 1,3,5,6,5,6,
    cout << "4) "; cout << v.size() << endl;
    //v中的元素没有减少,输出 4) 6
    return 0;
}

3.4 变序算法

变序算法改变容器中元素的顺序,但是不改变元素的值。变序算法不适用于关联容器。此类算法复杂度都是O(n)的。

  • reverse 颠倒区间的前后次序
  • reverse_copy 把一个区间颠倒后的结果拷贝到另一个区间,源区间不变
  • random_shuffle 随机打乱区间内元素的顺序,适用于能随机访问的容器。用之前要初始化伪随机数种子: srand(unsigned(time(NULL))); //#include < ctime >
  • next_permutation 将区间改为下一个排列(可自定义比较器)
  • prev_permutation 将区间改为上一个排列(可自定义比较器)
  • partition 把区间内满足某个条件的元素移到前面,不满足该条件的移到后面
  • stable_patition 把区间内满足某个条件的元素移到前面,不满足该条件的移到后面。而且对这两部分元素,分别保持它们原来的先后次序不变
  • rotate 将区间进行循环左移
  • rotate_copy 将区间以首尾相接的形式进行旋转后的结果拷贝到另一个区间,源区间不变

3.5 排序算法

  • sort 将区间从小到大排序(可自定义比较器)。
  • stable_sort 将区间从小到大排序,并保持相等元素间的相对次序(可自定义比较器)。
  • partial_sort 对区间部分排序,直到最小的n个元素就位(可自定义比较器),后面顺序不管。
  • partial_sort_copy 将区间前n个元素的排序结果拷贝到别处。源区间不变(可自定义比较器)。
  • nth_element 对区间部分排序,使得第n小的元素(n从0开始算)就位,而且比它小的都在它前面,比它大的都在它后面(可自定义比较器)。
  • make_heap 使区间成为一个“堆”(可自定义比较器),实现:建堆。
  • push_heap 将元素加入一个是“堆”区间(可自定义比较器),实现:在之前添加一个元素的基础上,将其上浮。
  • pop_heap 从 “堆”区间删除堆顶元素(可自定义比较器),实现:堆顶和最后一个元素互换后再下滤,容器大小不变。
  • sort_heap 将一个“堆”区间进行排序,排序结束后,该区间就是普通的有序区间,不再是 “堆”了(可自定义比较器)
//示例:堆排序的用法(官网)
int main () {
    int myints[] = {10,20,30,5,15};
    std::vector<int> v(myints, myints+5);
    std::make_heap (v.begin(), v.end());
    std::cout << "initial max heap   : " << v.front() << '\n';
    
    std::pop_heap (v.begin(), v.end()); v.pop_back(); //注意pop_heap之后要手动弹出
    std::cout << "max heap after pop : " << v.front() << '\n';
    v.push_back(99); std::push_heap (v.begin(), v.end()); //注意这两个联用
    std::cout << "max heap after push: " << v.front() << '\n';
    std::sort_heap (v.begin(), v.end());
    
    std::cout << "final sorted range :";
    for (unsigned i=0; i<v.size(); i++)
        std::cout << ' ' << v[i];
    std::cout << endl;
    return 0;
}

注意:

  • 最常用的是sort。sort实际上是快速排序,平均性能最优;但是最坏的情况下,性能可能非常差。如果要保证“最坏情况下”的性能,那么可以使用stable_sort,内部采用归并,用法同sort。
  • 排序算法需要随机访问迭代器的支持,因而不适用于关联容器和list(list可用list::sort)。
  • 堆排序中,在make_heap之后调用push_heap和pop_heap均能自动调整以保持堆的特性;但是pop_heap之后需要手动弹出最后一个废值,push_heap之前需要将值添加进容器中。

3.6 有序区间算法

有序区间算法要求所操作的区间是已经从小到大排好序的,而且需要随机访问迭代器的支持。所以有序区间算法不能用于关联容器和list。

  • binary_search 判断区间中是否包含某个元素,实现:检查x<y是否为true。
  • includes 判断是否一个区间中的每个元素,都在另一个区间中(不要求连续)。
  • lower_bound 查找最后一个不小于某值的元素的位置。
  • upper_bound 查找第一个大于某值的元素的位置。
  • equal_range 同时获取lower_bound和upper_bound。
  • merge 合并两个有序区间到第三个区间。
  • inplace_merge 将两个连续的有序区间原地合并为一个有序区间
  • set_union 将两个有序区间的并拷贝到第三个区间,若某个元素e在第一区间里出现n1次,在第二区间里出现n2次,则该元素在目标区间里出现max(n1,n2)次。
  • set_intersection 将两个有序区间的交拷贝到第三个区间,若某个元素e在第一区间里出现n1次,在第二区间里出现n2次,则该元素在目标区间里出现min(n1,n2)次。
  • set_difference 将两个有序区间的差拷贝到第三个区间,若有多个相同元素不在第二区间,则均拷贝到第三区间。
  • set_symmetric_difference 将两个有序区间的对称差(即异或)拷贝到第三个区间

3.7 数值算法

主要针对一个类

//类模板
template<size_t N>  
class bitset{
    …
};
//实际使用的时候,N是个整型常数,如bitset<40> bst
//bst是一个由40位组成的对象,用bitset的函数可以方便地访问任何一位。

bitset<N>& operator&=(const bitset<N>& rhs);
bitset<N>& operator|=(const bitset<N>& rhs);
bitset<N>& operator^=(const bitset<N>& rhs);
bitset<N>& operator<<=(size_t num);
bitset<N>& operator>>=(size_t num);
bitset<N>& set(); //全部设成1
bitset<N>& set(size_t pos, bool val = true); //设置某位
bitset<N>& reset(); //全部设成0
bitset<N>& reset(size_t pos); //某位设成0
bitset<N>& flip(); //全部翻转
bitset<N>& flip(size_t pos); //翻转某位

reference operator[](size_t pos); //返回对某位的引用
bool operator[](size_t pos) const; //判断某位是否为1
reference at(size_t pos);
bool at(size_t pos) const;
unsigned long to_ulong() const; //转换成整数
string to_string() const; //转换成字符串
size_t count() const; //计算1的个数
size_t size() const;
bool operator==(const bitset<N>& rhs) const;
bool operator!=(const bitset<N>& rhs) const;

bool test(size_t pos) const; //测试某位是否为 1
bool any() const; //是否有某位为1
bool none() const; //是否全部为0
bitset<N> operator<<(size_t pos) const;
bitset<N> operator>>(size_t pos) const;
bitset<N> operator~();
static const size_t bitset_size = N;
//注意:第0位在最右边

猜你喜欢

转载自www.cnblogs.com/inchbyinch/p/12398701.html