STL

99 阅读3分钟

在关于算法的竞赛题和面试题里面我们一般不手写数据结构(谁都不想为难自己),更不必怀疑大牛造的轮子,STL就这样成为了我们实现多快好省的利器

STL我们主要得掌握里面线程的数据结构算法

算法

此时我们的头文件里应有#include<algorithm>#include<bits/stdc++.h>

sort

sort(首地址,末地址):从首地址到末地址前的所有元素(不含末地址对应的元素),时间复杂度为nlognnlogn

int a[]={7,8,9,6,2,1};
sort(a+1,a+6);
for(int i=1;i<6;i++)    printf("%d ",*(a+i));
// output:1 2 6 8 9(不另外调用排序规则,默认从小到大)
sort(a,a+6,less<int>())
for(int i=1;i<6;i++)    printf("%d ",*(a+i));
// output:2 6 7 8 9
sort(a,a+6,greater<int>());
for(int i=1;i<6;i++)    printf("%d ",*(a+i));
// output:9 8 7 6 2
    struct 结构名
    {
        bool operator(const <T> &a1,const <T> &a2) const
        {
            //若a1在a2前面就return true
            //否则返回false
        }
    }
#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
struct Student
{
    char name[10];
    int id;
    double gpa;
};
Student students []={{"Wang",7,98},{"Zhu",8,99},{"Yi",9,100}};
struct StudentRule
{
    bool operator() (const Student &s1,const Student &s2) const
    {
        if(stricmp(s1.name,s2.name))  return true;
        return false;
    }
};
int main()
{
    sort(students,students+3,StudentRule());
    for(int i=0;i<3;i++)    
    printf("%s %d %lf\n",students[i].name,students[i].id,students[i].gpa);
    //output:
    Yi 9 100.000000
    Zhu 8 99.000000
    Wang 7 98.000000
    return 0;
}

Binary Search

binary-search

binary_search(首地址,末地址,值),查询首地址到末地址前的所有元素是否存在等于的元素(不含末地址对应的元素),使用之前必须保证该排序的范围所有元素有序,时间复杂度为O(logn)O(logn)

  int a[]={4,15,7,8,9,3,2};
  sort(a,a+7);
  printf("%d",binary_search(a,a+7,9));
  //output:1

lower_bound

T* lower_bound(首地址,末地址,值)查找从首地址到末地址前的元素下标最小的大于等于的元素,如果没有则指向末地址

T* lower_bound(首地址,末地址,值,自定义排序规则结构名())查找自定义排序规则中下标最小的排在后面的元素,如果没有则指向末地址

  int a[]={4,15,7,8,9,9,11,3,16};
  printf("%d ",sizeof(a)/sizeof(int));//output:9
  sort(a,a+9);
  printf("%d %d %d ",lower_bound(a,a+8,9)-a,lower_bound(a,a+7,16)-a,lower_bound(a,a+8,16)-a);//output:4 7 8

upper_bound

T* upper_bound(首地址,末地址,值)查找从首地址到末地址前的元素下标最小的大于的元素,如果没有则指向末地址 T* upper_bound(首地址,末地址,值,自定义排序规则结构名())查找自定义排序规则中下标最小的排在后面的元素,如果没有则指向末地址

  int a[]={4,15,7,8,9,9,11,3,16}; 
  sort(a,a+8);
  printf("%d %d ",upper_bound(a,a+8,9)-a,upper_bound(a,a+8,15)-a);//output:6 8
#include<iostream>
#include<algorithm>
using namespace std;
struct Rule
{
  bool operator() (const int &a1,const int &a2) const
  {
    return a1%10<a2%10;
  }
};
int main()
{
  int a[]={12,5,3,5,98,21,7};
  sort(a,a+7,Rule());
  for(int i=0;i<7;i++)  printf("%d ",a[i]);//output:21 12 3 5 57 98
  printf("%d %d ",lower_bound(a,a+7,16,Rule())-a,*lower_bound(a,a+7,16,Rule()));//output:5 7
  printf("%d %d ",upper_bound(a,a+7,18,Rule())-a,*lower_bound(a,a+7,18,Rule()));// output:7 0
  return 0;
}

数据结构

平衡二叉树

  • 面对大量数据,我们需要用到平衡二叉树的数据结构,它能将增加,删除,查找操作的时间复杂度控制在O(logn)O(logn)
  • 根据前文,好像可以用sort排序+二分,可是当要增加和删除元素时,就要重新排序,最后时间复杂度为O(n2logn)O(n^2logn),显然是不可行的(接下来的操作更简单明了)
  • 此时我们的头文件里应有#include<set>#include<map>
  • 注意该结构中数据的地址都在[start,end],因此end对应的元素不属于该数据结构,若使用find在该数据集中未找到某元素,则返回end

采用平衡二叉树结构的下列容器均被称为关联容器

set

  • 往其中插入元素,可以根据给定规则进行排序,如果没有给定规则则按默认的小到大的顺序排序
  • 不能有重复元素,因此可能插入元素不成功
#include<iostream>
#include<set>
using namespace std;
int main()
{
  int a[10]={4,15,7,8,9,11,20,3,2,2};
  set<int> st;
  for(int i=0;i<10;i++) st.insert(a[i]);//插入的是a[i]的copy,即是a[i]的值
  for(set<int>::iterator i=st.begin();i!=st.end();i++) printf("%d ",*i);//2 3 4 7 8 9 11 15 20 等价于for(auto it:st) printf("%d ",it);
  st.insert(2);
  pair<set<int>::iterator,bool> x=st.insert(2);//x.first指向插入元素,x.second表示是否成功插入
  cout<<*x.first<<" "<<x.second;//2 0
  st.erase(15);
  for(auto it:st) printf("%d ",it);//output:2 3 4 7 8 9 11 20
  printf("%d",st.end()==st.find(0));//output:1
  return 0;
}

multiset

  • 操作set基础上允许出现重复元素
#include<iostream>
#include<set>
using namespace std;
struct Rule
{
  bool operator() (const int &a,const int &b) const
  {
    return a%10<b%10;
  }
};
int main()
{
  int a[10]={4,15,7,8,9,11,20,3,2,2};
  multiset<int,Rule> st;
  for(int i=0;i<10;i++) st.insert(a[i]);
  for(multiset<int,Rule>::iterator i=st.begin();i!=st.end();i++)  printf("%d ",*i); //output:20 11 2 2 3 4 15 7 8 9 
  auto it=st.find(99);
  printf("%d %d ",it==st.end(),*it);//output:0 9(此时find(x)是按照排序规则,找到y既不能排在x前,也不能排在x后)
  it=st.find(6);
  printf("%d",it==st.end());//output:1(找不到符合规则的位置)
  st.clear();
  return 0;
}

map

  • 容器中的元素都是pair类型,map<T1(key),T2(value)> mp
  • 默认情况下容器中的元素按照它们各自元素的first排序,如果相同则比较second
  • 可根据元素的first来查找
  • 不允许出现重复的key相同的元素
//统计单词词频
#include<iostream>
#include<map>
#include<set>
#include<cstring>
using namespace std;
struct Word
{
  int times;
  string wd;
};
struct Rule
{
  bool operator() (const Word &a,const Word &b) const
  {
    if(a.times!=b.times)
      return a.times<b.times;
    else 
      return a.wd<b.wd;
  }
};
int main()
{
  string s;
  map<string,int> mp;
  set<Word,Rule> st;
  while(cin>>s)
  {
    mp[s]++;
  }
/*input:
Guangdong
Guangdong
Guangdong
Winnerway
Winnerway
Champion
*/
  for(auto it=mp.begin();it!=mp.end();it++)
  {
    Word tmp;
    tmp.wd=it->first;
    tmp.times=it->second;
    st.insert(tmp);
  }
  for(auto it=st.begin();it!=st.end();it++) 
    cout<<it->wd<<" "<<it->times;
 /*
 Champion 1
 Winnerway 2
 Guangdong 3
 */
  return 0;
}

multimap

  • 在map的基础上允许出现相同keypair

制作一个学生成绩登分系统,记录学生name,id,score,可以根据指令进行操作,A:添加学生信息,Q:查询当前比该学生高的最低分,如果没有则输出“nobody”

#include<map>
#include<string>
#include<iostream>
using namespace std;
struct StuInfo
{
  int id;
  char name[10];
};
int main()
{
  multimap<int,StuInfo> mp;
  int op;
  cin>>op;
  while(op--)
  {
    string s;
    cin>>s;
    if(s=="A")
    {
      int score;
      StuInfo stu;
      cin>>stu.id>>stu.name>>score;
      mp.insert(make_pair(score,stu));
    } 
    8
/*input:
A 4 Du 94
A 8 Zhu 98
A 7 Wang 97
A 9 Yi 99
A 11 Zhou 95
A 2 Zhou 95
Q 94
Q 99
*/
    else
    {
      int x;
      cin>>x;
      auto t=mp.upper_bound(x);
      if(t!=mp.end())
      {
        int v=t->first;
        for(auto it=t;it!=mp.end()&&it->first==v;it++)
        {
          printf("%d %s %d\n",it->second.id,it->second.name,it->first);
          /*output:
          11 Zhou 95
          2 Zhou 95
          
          Nobody
          */
        }
      }
      else printf("Nobody\n");
    }
  }
  return 0;
}