zoukankan      html  css  js  c++  java
  • ACM/ICPC竞赛

    09篇 ACM/ICPC竞赛之STL--algorithm


    <algorithm>无疑是STL中最大的一个头文件,它是由一大堆模板函数组成的。

    下面列举出<algorithm>中的模板函数:

     adjacent_find / binary_search / copy / copy_backward / count / count_if / equal / equal_range / fill / fill_n / find / find_end / find_first_of / find_if / for_each / generate / generate_n / includes / inplace_merge / iter_swap / lexicographical_compare / lower_bound / make_heap / max / max_element / merge / min / min_element / mismatch / next_permutation / nth_element / partial_sort / partial_sort_copy / partition / pop_heap / prev_permutation / push_heap / random_shuffle / remove / remove_copy / remove_copy_if / remove_if / replace / replace_copy / replace_copy_if / replace_if / reverse / reverse_copy / rotate / rotate_copy / search / search_n / set_difference / set_intersection / set_symmetric_difference / set_union / sort / sort_heap / stable_partition / stable_sort / swap / swap_ranges / transform / unique / unique_copy / upper_bound



    如果详细叙述每一个模板函数的使用,足够写一本书的了。还是来看几个简单的示例程序吧。

    示例程序之一,for_each遍历容器:

     1 #include <iostream>
     2 #include <vector>
     3 #include <algorithm>
     4 using namespace std;
     5 
     6 int Visit(int v) // 遍历算子函数
     7 {
     8 cout << v << " ";
     9 return 1;
    10 }
    11 
    12 class MultInt // 定义遍历算子类
    13 {
    14 private:
    15 int factor;
    16 public:
    17 MultInt(int f) : factor(f)
    18 {
    19 }
    20 void operator()(int &elem) const
    21 {
    22 elem *= factor;
    23 }
    24 };
    25 
    26 main()
    27 {
    28 vector<int> L;
    29 for (int i=0; i<10; i++) L.push_back(i);
    30 for_each(L.begin(), L.end(), Visit);
    31 cout << endl;
    32 for_each(L.begin(), L.end(), MultInt(2));
    33 for_each(L.begin(), L.end(), Visit);
    34 cout << endl;
    35 return 1;
    36 }
    37 
    38 程序的输出结果为:
    39 
    40 0 1 2 3 4 5 6 7 8 9
    41 0 2 4 6 8 10 12 14 16 18



    示例程序之二,min_element/max_element,找出容器中的最小/最大值:

     1 #include <iostream>
     2 #include <vector>
     3 #include <algorithm>
     4 using namespace std;
     5 
     6 main()
     7 {
     8 vector<int> L;
     9 for (int i=0; i<10; i++) L.push_back(i);
    10 vector<int>::iterator min_it = min_element(L.begin(), L.end());
    11 vector<int>::iterator max_it = max_element(L.begin(), L.end());
    12 cout << "Min is " << *min_it << endl;
    13 cout << "Max is " << *max_it << endl;
    14 return 1;
    15 }
    16 
    17 程序的输出结果为:
    18 
    19 Min is 0
    20 Max is 9



    示例程序之三,sort对容器进行排序:

     1 #include <iostream>
     2 #include <vector>
     3 #include <algorithm>
     4 using namespace std;
     5 void Print(vector<int> &L)
     6 {
     7 for (vector<int>::iterator it=L.begin(); it!=L.end(); it++)
     8 cout << *it << " ";
     9 cout << endl;
    10 }
    11 main()
    12 {
    13 vector<int> L;
    14 for (int i=0; i<5; i++) L.push_back(i);
    15 for (int i=9; i>=5; i--) L.push_back(i);
    16 Print(L);
    17 sort(L.begin(), L.end());
    18 Print(L);
    19 sort(L.begin(), L.end(), greater<int>()); // 按降序排序
    20 Print(L);
    21 return 1;
    22 }
    23 
    24 程序的输出结果为:
    25 
    26 0 1 2 3 4 9 8 7 6 5
    27 0 1 2 3 4 5 6 7 8 9
    28 9 8 7 6 5 4 3 2 1 0



    示例程序之四,copy在容器间复制元素:

     1 #include <vector>
     2 #include <algorithm>
     3 #include <iostream>
     4 using namespace std;
     5 main( )
     6 {
     7 // 先初始化两个向量v1和v2
     8 vector <int> v1, v2;
     9 for (int i=0; i<=5; i++) v1.push_back(10*i);
    10 for (int i=0; i<=10; i++) v2.push_back(3*i);
    11 
    12 cout << "v1 = ( " ;
    13 for (vector <int>::iterator it=v1.begin(); it!=v1.end(); it++)
    14 cout << *it << " ";
    15 cout << ")" << endl;
    16 
    17 cout << "v2 = ( " ;
    18 for (vector <int>::iterator it=v2.begin(); it!=v2.end(); it++)
    19 cout << *it << " ";
    20 cout << ")" << endl;
    21 
    22 // 将v1的前三个元素复制到v2的中间
    23 copy(v1.begin(), v1.begin()+3, v2.begin()+4);
    24 
    25 cout << "v2 with v1 insert = ( " ;
    26 for (vector <int>::iterator it=v2.begin(); it!=v2.end(); it++)
    27 cout << *it << " ";
    28 cout << ")" << endl;
    29 
    30 // 在v2内部进行复制,注意参数2表示结束位置,结束位置不参与复制
    31 copy(v2.begin()+4, v2.begin()+7, v2.begin()+2);
    32 
    33 cout << "v2 with shifted insert = ( " ;
    34 for (vector <int>::iterator it=v2.begin(); it!=v2.end(); it++)
    35 cout << *it << " ";
    36 cout << ")" << endl;
    37 return 1;
    38 }
    39 
    40 程序的输出结果为:
    41 
    42 v1 = ( 0 10 20 30 40 50 )
    43 v2 = ( 0 3 6 9 12 15 18 21 24 27 30 )
    44 v2 with v1 insert = ( 0 3 6 9 0 10 20 21 24 27 30 )
    45 v2 with shifted insert = ( 0 3 0 10 20 10 20 21 24 27 30 )

    STL in ACM

    容器(container):

    迭代器(iterator): 指针

    内部实现: 数组 // 就是没有固定大小的数组,vector 直接翻译是向量vector // T 就是数据类型,Alloc 是关于内存的一个什么东西,一般是使用默认参数。

    支持操作:

    begin(), //取首个元素,返回一个iterator

    end(), //取末尾(最后一个元素的下一个存储空间的地址)

    size(), //就是数组大小的意思

    clear(), //清空

    empty(), //判断vector 是否为空

    [ ] //很神奇的东东,可以和数组一样操作

    //举例: vector a; //定义了一个vector

    //然后我们就可以用a[i]来直接访问a 中的第i + 1 个元素!和数组的下标一模一样!

    push_back(), pop_back() //从末尾插入或弹出

    insert() O(N) //插入元素,O(n)的复杂度

    erase() O(N) //删除某个元素,O(n)的复杂度

    可以用于数组大小不定且空间紧张的情况

    Iterator 用法举例:

    int main(){

    int n,i;

    vector vi; //类似于我们定义一个数组,同 int vi[1000]; 但vector的大小是自动调整的

    vector ::iterator itr; //两个冒号

    while (scanf("%d",&n) != EOF) vi.push_back(n);

    for (i = 0 ; i < vi.size() ; i++) printf("%d ",vi[i]);

    for (itr = vi.begin() ; itr != vi.end() ; itr++)

    printf("%d ",*itr);

    return 0;

    }

    类似:双端队列,两头都支持进出

    支持push_front()和pop_front()

    是的精简版:) //栈,只支持从末尾进出

    支持push(), pop(), top()

    是的精简版 //单端队列,就是我们平时所说的队列,一头进,另一头出

    支持push(), pop(), front(), back()

    内部实现: 双向链表 //作用和vector 差不多,但内部是用链表实现

    list

    支持操作:

    begin(), end(), size(), clear(), empty()

    push_back(), pop_back() //从末尾插入或删除元素

    push_front(), pop_front()

    insert() O(1) //链表实现,所以插入和删除的复杂度的O(1)

    erase() O(1)

    sort() O(nlogn),不同于中的sort

    //不支持[ ]操作!

    内部实现: 红黑树 //Red-Black Tree,一种平衡的二叉排序树

    set //又是一个Compare 函数,类似于qsort 函数里的那个Compare 函数,

    作为红黑树在内部实现的比较方式

    insert() O(logn)

    erase() O(logn)

    find() O(logn) 找不到返回a.end()

    lower_bound() O(logn) 查找第一个不小于k 的元素

    upper_bound() O(logn) 查找第一个大于k 的元素

    equal_range() O(logn) 返回pair

    42

    允许重复元素的

    的用法及Compare 函数示例:

    struct SS {int x,y;};

    struct ltstr {

    bool operator() (SS a, SS b)

    {return a.x < b.x;} //注意,按C 语言习惯,double 型要写成这样:

    return a.x < b.x ? 1 : 0;

    };

    int main() {

    set st;

    }

    内部实现: pair 组成的红黑树 //map 中文意思:映射!!

    map //就是很多pair 组成一个红黑树

    insert() O(logn)

    erase() O(logn)

    find() O(logn) 找不到返回a.end()

    lower_bound() O(logn) 查找第一个不小于k 的元素

    upper_bound() O(logn) 查找第一个大于k 的元素

    equal_range() O(logn) 返回pair

    [key]运算符 O(logn) *** //这个..太猛了,怎么说呢,数组有一个下标,如a[i],这里i 是int 型的。数组可以认为是从int 印射到另一个类型的印射,而map 是一个任意的印射,所以i 可以是任何类型的!允许重复元素, 没有[]运算符

    内部实现: 堆 //优先队列,听RoBa 讲得,似乎知道原理了,但不明白干什么用的

    priority_queue

    支持操作:

    push() O(n)

    pop() O(n)

    top() O(1)

    See also: push_heap(), pop_heap() … in

    用法举例:

    priority_queue maxheap; //int 最大堆

    struct ltstr { //又是这么个Compare 函数,重载运算符???不明白为什么要这么写...反正这个Compare 函数对我来说是相当之神奇。RoBa

    说了,照着这么写就是了。

    bool operator()(int a,int b)

    {return a > b;}

    };

    priority_queue <INT,VECTOR,ltstr> minheap; //int 最小堆

    1.sort()

    void sort(RandomAccessIterator first, RandomAccessIterator

    last);

    void sort(RandomAccessIterator first, RandomAccessIterator

    last, StrictWeakOrdering comp);

    区间[first,last)

    Quicksort,复杂度O(nlogn)

    (n=last-first,平均情况和最坏情况)

    用法举例:

    1.从小到大排序(int, double, char, string, etc)

    const int N = 5;

    int main()

    {

    int a[N] = {4,3,2,6,1};

    string str[N] = {“TJU”,”ACM”,”ICPC”,”abc”,”kkkkk”};

    sort(a,a+N);

    sort(str,str+N);

    return 0;

    }

    2.从大到小排序(需要自己写comp 函数)

    const int N = 5;

    int cmp(int a,int b) {return a > b;}

    int main()

    {

    int a[N] = {4,3,2,6,1};

    sort(a,a+N,cmp);

    return 0;

    }

    3. 对结构体排序

    struct SS {int first,second;};

    int cmp(SS a,SS b) {

    if (a.first != b.first) return a.first < b.first;

    return a.second < b.second;

    }

    v.s. qsort() in C (平均情况O(nlogn),最坏情况

    O(n^2)) //qsort 中的cmp 函数写起来就麻烦多了!

    int cmp(const void *a,const void *b) {

    if (((SS*)a)->first != ((SS*)b)->first)

    return ((SS*)a)->first – ((SS*)b)->first;

    return ((SS*)a)->second – ((SS*)b)->second;

    }

    qsort(array,n,sizeof(array[0]),cmp);

    sort()系列:

    stable_sort(first,last,cmp); //稳定排序

    partial_sort(first,middle,last,cmp);//部分排序

    将前(middle-first)个元素放在[first,middle)中,其余元素位置不定

    e.g.

    int A[12] = {7, 2, 6, 11, 9, 3, 12, 10, 8, 4, 1, 5};

    partial_sort(A, A + 5, A + 12);

    // 结果是 "1 2 3 4 5 11 12 10 9 8 7 6".

    Detail: Heapsort ,

    O((last-first)*log(middle-first))

    sort()系列:

    partial_sort_copy(first, last, result_first, result_last,

    cmp);

    //输入到另一个容器,不破坏原有序列

    bool is_sorted(first, last, cmp);

    //判断是否已经有序

    nth_element(first, nth, last, cmp);

    //使[first,nth)的元素不大于[nth,last), O(N)

    e.g. input: 7, 2, 6, 11, 9, 3, 12, 10, 8, 4, 1, 5

    nth_element(A,A+6,A+12);

    Output: 5 2 6 1 4 3 7 8 9 10 11 12

    2. binary_search()

    bool binary_search(ForwardIterator first, ForwardIterator

    last, const LessThanComparable& value);

    bool binary_search(ForwardIterator first, ForwardIterator

    last, const T& value, StrictWeakOrdering comp);

    [first,last)中查找value,如果找到返回Ture,否则返回False

    二分检索,复杂度O(log(last-first))

    v.s. bsearch() in C

    Binary_search()系列

    itr upper_bound(first, last, value, cmp);

    //itr 指向大于value 的第一个值(或容器末尾)

    itr lower_bound(first, last, value, cmp);

    //itr 指向不小于valude 的第一个值(或容器末尾)

    pair equal_range(first, last, value, cmp);

    //找出等于value 的值的范围 O(2*log(last – first))

    int A[N] = {1,2,3,3,3,5,8}

    *upper_bound(A,A+N,3) == 5

    *lower_bound(A,A+N,3) == 3

    make_heap(first,last,cmp) O(n)

    push_heap(first,last,cmp) O(logn)

    pop_heap(first,last,cmp) O(logn)

    is_heap(first,last,cmp) O(n)

    e.g:

    vector vi;

    while (scanf(“%d”,&n) != EOF) {

    vi.push_back(n);

    push_heap(vi.begin(),vi.end());

    }

    Others interesting:

    next_permutation(first, last, cmp)

    prev_permutation(first, last, cmp)

    //both O(N)

    min(a,b);

    max(a,b);

    min_element(first, last, cmp);

    max_element(first, last, cmp);

    Others interesting:

    fill(first, last, value)

    reverse(first, last)

    rotate(first,middle,last);

    itr unique(first, last);

    //返回指针指向合并后的末尾处

    random_shuffle(first, last, rand)

    头文件

    #include <vector>

    #include <list>

    #include <map>

    #include <set>

    #include <deque>

    #include <stack>

    #include <bitset>

    43

    #include <algorithm>

    #include <functional>

    #include <numeric>

    #include <utility>

    #include <sstream>

    #include <iostream>

    #include <iomanip>

    #include <cstdio>

    #include <cmath>

    #include <cstdlib>

    #include <ctime>

    using namespace std;

    未完待续……

     

     

     

  • 相关阅读:
    archlinux .bash_history
    Ubuntu环境下挂载新硬盘
    软碟通 UltraISO U启替代品 Win32DiskImager 无设备 无盘符 无u盘 无优盘 解决方案 之diskpart
    delphi Integer overflow
    MSBuild Tools offline
    delphi synedit免费的拼写检查器dll
    git 自定义命令行
    lua编译
    gcc ar
    Windows Subsystem for Linux (WSL)挂载移动硬盘U盘 卸载 c d 盘
  • 原文地址:https://www.cnblogs.com/jeff-wgc/p/4480343.html
Copyright © 2011-2022 走看看