备战蓝桥杯从STL库开始---最简单的几个容器

备战蓝桥杯从STL库开始—最简单的几个常用容器

1、STL库的介绍

学习C/C++语言的基础很简单,但是写写算法的能力不是人人都具备的,本人蒟蒻一枚,时常感觉算法的概念原理都懂,但就是写不出来东西,于是发现了一个“百宝箱”——STL(Standard Template Library,标准模板库)
一般分为algorithm(算法)、container(容器)和iterator(迭代器)三类。模板库内容主要包含了一些常用的算法如快速排序、简单查找等,当然还包括了一些常用的数据结构,如可变长数组、链表、字典等。
一般以它的高效著称。注解:打比赛return 0少不了!!!

2、基础知识

  1. 快速排序sort

    sort排序是学习STL必须要知道的,内部算法结构是快速排序,不懂的同学可以先去了解一下快排的原理,毕竟手打快排也有可能在比赛场上需要。

    #include<iostream>
    #include<algorithm>
    #include<cstdlib> 
    using namespace std;
    int main(){
    	int a[10];
    	for(int i=0;i<10;i++){
    		a[i]=rand()%100;//存入十个随机数 
    	}
    	for(int i=0;i<10;i++){
    		cout<<a[i]<<" ";
    	}
    	cout<<endl; 
    	sort(a+0,a+10);//默认是从小到大排序
    	//其中第一个参数 代表数组的起始一个元素的位置,第二个参数代表数组最后一个元素的起始位置
    	//只要你愿意,你可以只排序一部分的数据试一试。
    	for(int i=0;i<10;i++){
    		cout<<a[i]<<" ";
    	} //排序结果 
    }
    

    在这里插入图片描述

    那么如何从大到小排序呢?

    其实sort方法有内置好的方法让你从大到小排序,在这里,我们讲一下如何自己写一个方法从大到小排序。

    #include<iostream>
    #include<algorithm>
    #include<cstdlib> 
    using namespace std;
    bool cmp(int x,int y){//这里的参数一定要是你排序类型的参数
    	return x>y;//从大到小排序 
    }
    int main(){
    	int a[10];
    	for(int i=0;i<10;i++){
    		a[i]=rand()%100;//存入十个随机数 
    	}
    	for(int i=0;i<10;i++){
    		cout<<a[i]<<" ";
    	}
    	cout<<endl; 
    	sort(a+0,a+10,cmp);//默认是从小到大排序
    	//其中第一个参数 代表数组的起始一个元素的位置,第二个参数代表数组最后一个元素的起始位置
    	//只要你愿意,你可以只排序一部分的数据试一试。
    	for(int i=0;i<10;i++){
    		cout<<a[i]<<" ";
    	} //排序结果 
    }
    
     ![在这里插入图片描述](https://img-blog.csdnimg.cn/202104090001127.png)
    

    ​ 一般sort排序是针对字典序进行排序,所以当你是字符串数组的时候也是可以进行排序的,这一点大家可以自行尝试。同时还支持double类型的排序,也可以尝试一下。

    ​ 针对结构体数据也可以使用sort进行排序,我们以输入学生成绩进行排序为例子,每个学生都有3门课的成绩:语文、数学、英语。先按总分从高到低排序,如果两个同学总分相同,再按语文成绩从高到低排序,如果两个同学总分和语文成绩都相同,那么规定学号小的同学排在前面。

    #include<iostream>
    #include<algorithm>
    using namespace std;
    int n;
    struct stu{
    	int num;//学号 
    	int c,m,e;//三科成绩 
    	int sum;//总分 
    }student[310];//定义学生的结构体类型 
    bool cmp(stu a,stu b){
    	if(a.sum>b.sum){
    		return a.sum>b.sum;
    	}else if(a.sum<b.sum){
    		return 0;
    	}else{
    		if(a.c>b.c){
    			return a.c>b.c;
    		}else if(a.c<b.c){
    			return 0;
    		}else{
    			return a.num < b.num;
    		}
    	}
    }
    int main(){
    	cin >> n;
    	for(int i=1;i<=n;i++){
    		student[i].num=i;
    		cin>>student[i].c>>student[i].m>>student[i].e;
    		student[i].sum=student[i].c+student[i].m+student[i].e;
    	}
    	sort(student+1,student+n+1,cmp);
    	for(int i=1;i<=5;i++)
            cout<<student[i].num<<' '<<student[i].sum<<endl;
    	return 0;
    }
    
  2. vector 向量容器

    vector 向量容器是一种简单高效的容器,在尾端插入和删除元素,算法时间为O(1),其他元素插入和删除时间为O(n)。vector可动态调整所占用的内存空间。

    在此之前导入**#include**

    vector,T代表类型,类似于你定义数组的类型一样。

    也被称为动态数组,当你做题目的时候如果遇到数组空间大小不确定的情况下,可以考虑使用它,同样也很高效,首先要了解它常用的几种方法。

    1. 如何存数据?

      #include<iostream>
      #include<vector>
      using namespace std;
      
      
      
      int main(){
      	vector < int > v ;
      	v.push_back(30);                                    //此时是从尾端插入新元素
      	v.push_back(23);
      	v.push_back(11);
      	return 0;
      }
      
    2. 如何取数据

      1. 采取数组的方式读取数据

        #include<iostream>
        #include<vector>
        using namespace std;
        
        int main(){
        	vector < int > v ;
        	v.push_back(30);                                    //此时是从尾端插入新元素
        	v.push_back(23);
        	v.push_back(11);
        	for(int i = 0 ; i < v.size() ; i++ ){
        		cout<<v[i]<<' ';
        	}
        	return 0;
        }
        
      2. 采取迭代器的方式读取数据

      #include<iostream>
      #include<vector>
      using namespace std;
      int main(){
      	int j ;
      	vector < int > v ;
      	v.push_back (11) ;                                    //尾插入新元素
      	v.push_back (23) ;
      	//	v.clear () ;                                      //清空全部元素             
      	v.push_back (30) ;
          v.push_back(1);
          v.push_back(16);
      	v.insert ( v.begin() + 3 , 41 ) ;                     //插入41在第3个元素的后面
          //一定要去动手验证一下结果
      	v.insert ( v.begin(), 15 ) ;                        //插入15为首元素
      	v.insert ( v.end(), 12 ) ;                          //插入12为末元素
          
      	v.erase ( v.begin() + 2) ;                           //删除第三个元素
      	v.erase ( v.begin() , v.begin() + 2 ) ;              //删除前三个元素
       	
          //迭代器访问
          vector < int > :: iterator i ;                     
       	for( i=v.begin(),j=0;i!=v.end();i++,j++ ){//从头到尾来进行扫描
       		cout<<"v["<<j<<"]="<< *i <<endl;//*号必不可少
       	}
          
       	swap(v[1],v[3]);   //交换元素
          
          for( i = v.begin() , j = 0 ; i != v.end() ; i++ , j++ ){
       		cout<<" v[ "<<j<<" ]= "<<*i<<endl;
       	}//审查元素
      
       	cout<<v.empty()<<endl;                               //判断是否为空
       	cout<<v.size()<<endl;                                //元素实际个数
       	cout<<v.max_size()<<endl;                            //可容纳的最大元素个数
       	cout<<v.capacity()<<endl;                            //当前可容纳的最大元素个数
       	cout<<v.front()<<endl;                               //首元素引用
       	cout<<v.back()<<endl;                                //末元素引用
      
       	v.pop_back();                                        //删除末尾的一个元素
       	v.reserve(30);                                       //调整数据空间大小
       	cout<<v.capacity()<<endl;
       	
          vector < int > :: reverse_iterator re ;              //反向迭代器
       	for( re = v.rbegin() ; re != v.rend() ; re++ ){      //转置方法
       		cout<<*ri<<endl;
       	}
      	return 0;
      }
      
    3. 结构体容器

      #include<iostream>
      #include<vector>
      using namespace std;
      
      struct stu{
      	int x;
      	int y;
      };
      
      int main()
      {
      	int j ;
      	vector <stu> v1 ;                                  //声明结构体容器
      	vector <stu> v2 ;
      	struct stu a1={1,2};
      	struct stu a2={2,3};
      	struct stu a3={4,5} ;
      	v1.push_back( a );
      	v1.push_back( b );
      	v1.push_back( c );
          //压入数据
      	v2.push_back( c );
      	v2.push_back( b );
      	v2.push_back( a );
      	//读取出数据
      	for(int i=0; i<v1.size(); i++ ){
      		cout<<v1[i].x<<' '<<v1[i].y<<'\n';
      	}
      
      	for(inti=0; i<v2.size(); i++ ){
      		cout<<v2[i].x<<' '<<v2[i].y<<'\n';
      	}
          
      	swap(v1,v2);                                              //两结构体元素交换
      	for(int i=0; i<v1.size(); i++ ){
      		cout<<v1[i].x<<' '<<v1[i].y<<'\n';
      	}
      
      	for(inti=0; i<v2.size(); i++ ){
      		cout<<v2[i].x<<' '<<v2[i].y<<'\n';
      	}
      	return 0;
      }
      

      更多的vector 的使用,还得到实际的场景中去实际操作。

  3. set容器

    set集合容器使用一种红黑树的平均二叉检索树,不会将重复键值插入,检索使用二叉树的中序遍历,因此可以将元素从小到大排列出来。同时保证数据不重复,可以理解为集合中元素不重复一样

    使用时注意包含头文件**#include**

    1.set容器的常用操作

    s.begin()      返回set容器的第一个元素
    s.end()      返回set容器的最后一个元素
    s.clear()       删除set容器中的所有的元素
    s.empty()     判断set容器是否为空
    s.insert()      插入一个元素
    s.erase()       删除一个元素
    s.size()     返回当前set容器中的元素个数
    

    2.set容器的创建

    #include <iostream>
    #include <set>
    using namespace std;
    
    int main(){
    	set<int> s;
    }
    

    3.set容器的操作

    //插入操作
    #include <iostream>
    #include <set>
    using namespace std;
    int main(){
    	set<int >s;
        int cnt = 1;
        s.insert(1);
        s.insert(2);
        s.insert(5);
        for(set<int>::iterator it = s.begin(); it!= s.end(); it++)
            cout << *it << " ";
        s.insert(2); //set只允许用一个值出现一次,要插入相同元素请用multiset
    	for(set<int>::iterator it = s.begin(); it!= s.end(); it++)
            cout << *it << " ";
            
        int a[4] = {11,12,13,14};
        s.insert(a,a+4); //将区间[a, a+4]里的元素插入容器
     	for(set<int>::iterator it = s.begin(); it!= s.end(); it++)
            cout << *it << " ";
        return 0;
    }
    
    //删除操作
    //s.erase()       //删除一个元素
    #include <iostream>
    #include <set>
    using namespace std;
    set<int >s;
    int main(){
        int cnt = 1;
        for(int i = 1; i < 11; i++){
            s.insert(i);
        }
        setprint(cnt++);
     
        s.erase(9); //根据元素删除
        for(set<int>::iterator it = s.begin(); it!= s.end(); it++)
            cout << *it << " ";
     
        set<int>::iterator ita = s.begin();
        set<int>::iterator itb = s.begin();
        s.erase(ita);  //删除迭代器指向位置的元素
        for(set<int>::iterator it = s.begin(); it!= s.end(); it++)
            cout << *it << " ";
     
        ita = s.begin();
        itb = s.begin();
        itb++;itb++;
        s.erase(ita,itb); //删除区间[ita,itb)的元素
        for(set<int>::iterator it = s.begin(); it!= s.end(); it++)
            cout << *it << " ";
        s.clear();
        return 0;
    }
    
    //查找操作
    //s.find()        查找一个元素,如果容器中不存在该元素,返回值等于s.end()
    #include <iostream>
    #include <set>
    using namespace std;
    set<int >s;
    int main(){
        int cnt = 1;
        s.insert(1);
        s.insert(2);
        s.insert(5);
        for(set<int>::iterator it = s.begin(); it!= s.end(); it++)
            cout << *it << " ";
     
        if(s.find(2) != s.end()) 
            cout << "2 is existent" << endl;
        else 
            cout << "2 is non-existent" << endl;
        if(s.find(3) == s.end()) 
            cout << "3 is non-existent" << endl;
        else 
            cout << "2 is existent" << endl;
        return 0;
    }
    
    //判断元素是否在set中 & 判断set是否为空
    #include <iostream>
    #include <set>
    #include <functional>
    using namespace std;
    int main(){
        set<int > s;
        if(s.empty()) cout << "容器为空" << endl;
        s.insert(1);
        if(!s.empty()) cout << "容器不为空" << endl;
     
        if(s.count(1)) cout << "1在容器中" << endl;
        if(!s.count(2)) cout << "2不在容器中" << endl;
        return 0;
    }
    
    //自定义比较函数
    #include <iostream>
    #include <set>
    #include <functional>
    using namespace std;
     
    struct cmp{
        bool operator () (const int &a, const int &b){
            return a > b;
        }
    };
    set<int, cmp>s; //自定义排序函数构造set
    int main(){
        s.insert(1);
        s.insert(2);
        s.insert(6);
        for(set<int,cmp>::iterator it = s.begin(); it!= s.end(); it++)
            cout << *it << " ";
        return 0;
    }
    
  4. stack容器

    stack,俗称为“栈”。可以先去了解一下栈结构再来看看。

    由于栈是后进后出的数据结构,因此STL中的stack中只能通过top()来访问栈顶元素。用来模拟实现一些递归。(防止程序对栈内存的限制而导致程序运行错误)

    一般来说,程序的栈内存空间很小,若用普通的函数来递归,一旦层数过深,则会导致程序运行崩溃。用栈来模拟递归算法的实现,则可以避免这一方面的问题.

    导入前加入头文件#include

    1. 常见操作

      empty:判断堆栈元素是否为空,true表示栈元素为空;
      pop:移除栈顶元素;
      push:栈顶添加元素;
      top:返回栈顶元素;
      size:返回栈中元素数目;
      
    2. 具体实现

      #include<iostream>
      #include<stack>
      using namespace std;
      int main(){
          stack<int> st;
          if(st.empty()==true){//输出Empty
              printf("Empty\n");
          }else{
              printf("Not Empty\n");
          }
          for(int i  = 1; i < 5; i++){
              st.push(i);
          }
          printf("%d\n",st.top);//top()取栈顶元素,输出为5
          printf("%d\n",st.size());
          for(int i  = 1; i < 5; i++){
              st.pop(i);
          }
          printf("%d\n",st.top);//top()取栈顶元素,输出为5
          printf%d\n",st.size());
      }
      
  5. queue容器

    queue与stack模版非常类似,queue模版也需要定义两个模版参数,一个是元素类型,一个是容器类型,元素类型是必要的,容器类型是可选的,默认为dqueue类型。

    队列的知识建议百度搜一下就懂了,提前知道什么是队列再看。

    queue<int> q1;
    queue<double> q2;
    
    1. 基本操作

      入队,如例:q.push(x); 将x 接到队列的末端。
      出队,如例:q.pop(); 弹出队列的第一个元素,注意,并不会返回被弹出元素的值。
      访问队首元素,如例:q.front(),即最早被压入队列的元素。
      访问队尾元素,如例:q.back(),即最后被压入队列的元素。
      判断队列空,如例:q.empty(),当队列空时,返回true。
      访问队列中的元素个数,如例:q.size()
      
    2. 具体实现

      #include <cstdlib>
      #include <iostream>
      #include <queue>
        
      using namespace std;
        
      int main()
      {
          int e,n,m;
          queue<int> q1;
          for(int i=0;i<10;i++)
             q1.push(i);
          if(!q1.empty())
          cout<<"dui lie  bu kong\n";
          n=q1.size();
          cout<<n<<endl;
          m=q1.back();
          cout<<m<<endl;
          for(int j=0;j<n;j++)
          {
             e=q1.front();
             cout<<e<<" ";
             q1.pop();
          }
          cout<<endl;
          if(q1.empty())
          cout<<"dui lie  bu kong\n";
          system("PAUSE");
          return 0;
      }
      

    队列中还有很多知识,其中最重要的是优先队列,这个要花一些时间去理解,往后再说,同时利用优先队列做的题目也不再少数,很多都是搜索方面的题目,下一次一起拿一些题目一起单独聊聊优先队列和大小堆的知识点

  • 5
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 5
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值