• 初涉算法——STL初步


    一、头文件<algorithm>

    ①sort函数

    • sort使用数组元素默认的大小比较运算符进行排序,只有在需要按照特殊依据进行排序时才需要传入额外的比较函数;
    • sort可以给任意对象排序(不一定是内置类型,由此可见sort是模板函数),前提是类型需要定义“小于”运算符,或者在排序时传入一个“小于”函数;
    • 排序对象若存在普通数组中,则用sort(a, a+n)的方式调用;
    • 排序对象若存在vector中,则用sort(v.begin(), v.end())。
     1 #include<algorithm>
     2 const int maxn = 10000;
     3 int main()
     4 {
     5     int n, a[maxn];
     6     for(int i=0;i<n;i++){
     7         scanf("%d",&a[i]);
     8     }
     9     sort(a,a+n);
    10 }

    ②lower_bound函数

    • 查找大于或者等于x的第一个位置
    • 可以在用sort函数排好序后再使用lower_bound
     1 #include<algorithm>
     2 const int maxn = 10000;
     3 int main()
     4 {
     5     int n, a[maxn];
     6     for(int i=0;i<n;i++)
     7         scanf("%d",&a[i]);
     8     sort(a,a+n);
     9     scanf("%d",&x);
    10     int p = lower_bound(a, a+n, x) - a;  //在已排序数组a中寻找x 
    11     if(a[p]==x)
    12         printf("%d found at %d
    ", x, p+1); 
    13 }

    二、头文件<vector>

    ①特点:它把一些常用操作“封装”在了vector类型内部(例如:函数size()可以读取其大小)。

    ②区别于数组:无需另外用一个变量(maxn)指定元素个数。

    ③优点:可以直接赋值,还可以作为函数的参数或者返回值。

    vector是一个模板类:

     1 int main()
     2 {
     3     vector<int> a;                //声明一个不定长int型数组a 
     4     a.push_back(1);               //在尾部添加元素1 
     5     a.pop_back();                 //在尾部删除元素 
     6     cout<<a.size();               //输出a的大小
     7     a.resize(4);                  //修改a的大小为4 
     8     a.clear();                    //清空a,此时a的大小为0 
     9     bool isEmpty = a.empty();     //a为空,则isEmpty被赋值为true 
    10 }

    三、头文件<set>

    定义:set是数学上的集合——每个元素最多只能出现一次。

    特点:和sort一样,自定义类型也可以构造set,但必须定义“小于”运算符。

    性质:set中元素已从小到大排好序。

    题目:输入一个文本,找出所有不同的单词(连续的字母序列),按字典序从小到大输出,单词不区分大小写。

     1 #include<iostream>
     2 #include<string>
     3 #include<set>
     4 #include<sstream>
     5 using namespace std;
     6 
     7 set<string> dict;                      //声明string集合 
     8 string s, buf;
     9 
    10 int main() 
    11 {
    12   while(cin >> s) {                        //注意:string已经定义了"小于"运算符,可直接使用set保存单词集合 
    13     for(int i = 0; i < s.length(); i++)    //利用了set的性质,一个for循环即可从小到大遍历所有元素 
    14       if(isalpha(s[i]))                   //判定s[i]是否为字母 
    15           s[i] = tolower(s[i]);             //全都转为小写 
    16       else 
    17           s[i] = ' ';     
    18     stringstream ss(s);
    19     while(ss >> buf)                     
    20         dict.insert(buf);
    21   }
    22   for(set<string>::iterator it = dict.begin(); it != dict.end(); ++it)//利用了set的性质,一个for循环即可从小到大遍历所有元素
    23     cout << *it << "
    ";            //迭代器it的用法之一 
    24   return 0;
    25 }

    四、头文件<map>

    定义:map就是从键(key)到值(value)的映射。

    特点:重载了[]运算符,map像是数组的“高级版”。

    举例:用map<string,int> month_name来表示“月份名字到月份编号”的映射,然后用month_name["July"]=7这样的方式来赋值。

    题目:输入一些单词,找出所有满足如下条件的单词:该单词不能通过字母重排而得到输入文本中的另外一个单词。字母不区分大小写。

     1 #include<iostream>
     2 #include<string>
     3 #include<cctype>
     4 #include<vector>
     5 #include<map>
     6 #include<algorithm>
     7 using namespace std;
     8 
     9 map<string,int> cnt;                
    10 vector<string> words;
    11 
    12 
    13 string repr(string s)                //将单词s进行标准化 
    14 {
    15   string ans = s;
    16   for(int i = 0; i < ans.length(); i++)
    17     ans[i] = tolower(ans[i]);
    18   sort(ans.begin(), ans.end());
    19   return ans;
    20 }
    21 
    22 int main() {
    23   int n = 0;
    24   string s;
    25   while(cin >> s) {
    26     if(s[0] == '#') break;
    27     words.push_back(s);
    28     string r = repr(s);
    29     if(!cnt.count(r))     //set和map都支持insert、find、count和remove操作,并且可以按照从小到大的顺序循环遍历其中的元素
    30         cnt[r] = 0;     
    31     cnt[r]++;
    32   }
    33   vector<string> ans;
    34   for(int i = 0; i < words.size(); i++)
    35     if(cnt[repr(words[i])] == 1) 
    36         ans.push_back(words[i]);
    37   sort(ans.begin(), ans.end());
    38   for(int i = 0; i < ans.size(); i++)
    39     cout << ans[i] << "
    ";
    40   return 0;
    41 }

    小结:set和map都支持insert、find、count和remove操作,并且可以按照从小到大的顺序循环遍历其中的元素。此外,map还提供了“[]”运算符,使得map可以像数组一样使用。

    五、头文件<stack>

    • 定义:stack<int> s
    • 入栈:push()
    • 出栈:pop()
    • 取栈顶元素:top()

    题目:Uva12096

     1 #include<iostream>
     2 #include<string>
     3 #include<set>
     4 #include<map>
     5 #include<stack>
     6 #include<vector>
     7 #include<algorithm>
     8 using namespace std;
     9 
    10 #define ALL(x) x.begin(),x.end()
    11 #define INS(x) inserter(x,x.begin())
    12 
    13 typedef set<int> Set;
    14 map<Set,int> IDcache; //把集合映射成ID
    15 vector<Set> Setcache; //根据ID取集合 
    16 
    17 //查找给定集合x的ID。如果找不到,分配一个新ID 
    18 int ID (Set x) {
    19   if (IDcache.count(x)) return IDcache[x];
    20   Setcache.push_back(x);     //添加新集合 
    21   return IDcache[x] = Setcache.size() - 1;
    22 }
    23 
    24 int main () {
    25   int T;
    26   cin >> T;
    27   while(T--) {
    28     stack<int> s; //题目中的栈 
    29     int n;
    30     cin >> n;
    31     for(int i = 0; i < n; i++) {
    32       string op;
    33       cin >> op;
    34       if (op[0] == 'P') s.push(ID(Set()));
    35       else if (op[0] == 'D') s.push(s.top());
    36       else {
    37         Set x1 = Setcache[s.top()]; s.pop();
    38         Set x2 = Setcache[s.top()]; s.pop();
    39         Set x;
    40         if (op[0] == 'U') set_union (ALL(x1), ALL(x2), INS(x));
    41         if (op[0] == 'I') set_intersection (ALL(x1), ALL(x2), INS(x));
    42         if (op[0] == 'A') { x = x2; x.insert(ID(x1)); }
    43         s.push(ID(x));
    44       }      
    45       cout << Setcache[s.top()].size() << endl;
    46     }
    47     cout << "***" << endl;
    48   }
    49   return 0;  
    50 }

    六、头文件<queue>

    • 定义:queue<int> s
    • 入队:push()
    • 出队:pop()
    • 取队首元素:front()

    【优先队列】

    区别于队列:先出队列的元素是队列中优先级最高的元素。

    声明:priority_queue<int> pq     //pq是一个“越小的整数优先级越低的优先队列”

    取队首元素:top()

    注:自定义类型也可以组成优先队列,但必须为每个元素定义一个优先级。

  • 相关阅读:
    2020Java面试题及答案,刷这些题,准没错!
    作为一个面试官,我想问问你Redis分布式锁怎么搞?
    你说研究过Spring里面的源码,循环依赖你会么?
    一口气说出 6种 延时队列的实现方案,面试稳稳的
    我可真是醉了,一个SpringBoot居然问了我30个问题
    最强Dubbo面试题,附带超级详细答案
    平安银行Java社招五面面经,目前最全面的,38个面试题以及答案
    Java电子书高清PDF集合免费下载
    Python处理json模块的详细介绍
    用Python写一个“离线语音提示器”来提醒我们别忘记了时间
  • 原文地址:https://www.cnblogs.com/xzxl/p/7219809.html
Copyright © 2020-2023  润新知