C++STL库 笔记

#include <bits/stdc++.h>
using namespace std;
int j=12;
void puttt(std::vector<int> v2)
{
      std::cout <<j<< ": "; 
    for(int i=0;i<v2.size();i++)
    {
        std::cout << v2[i] << " ";
    }
    std::cout <<std::endl; 
    std::cout <<std::endl; 
    std::cout <<std::endl;   
    std::cout <<std::endl; 
    j++;
}
int shi(int a)
{
    return a<15;
}
int main()

{
    int arr[]={1,2,3,4,5};
    
    
    std::vector<int/*元素类型*/> v1(arr,arr+5);
 //1.vector(begin,end)(两个指针)构造函数将前闭后开区间中元素拷贝给本身 
    
    
    std::vector<int >v2(5,10);
 //2.vector(n,elem)将n个elem拷贝给本身 
    
    
    std::vector<int> v3(v1);
//拷贝构造函数 
    
    
    std::vector<int> v4;
    std::vector<int> v5;
    std::vector<int> v6;

    v4.assign(v2.begin(),v2.end());
  //将前闭后开的指针中间的值赋值给v2;end()函数指向末尾的下一位;
  //也可以像v2一样赋值;


    v5=v1;
    //重载等号操作符; 
    
    
    v6=v2; 
    std::cout << "1: "; 


//1 
    for(int i=0;i<5;i++)
    {
        std::cout << v1[i] << " ";
    }
    std::    cout << std::endl; 
 std::cout << "2: "; 


//2
    for(int i=0;i<5;i++)
    {
        std::cout << v2[i] << " ";
    }
    std::cout << std::endl; 
 std::cout << "3: "; 


//3
    for(int i=0;i<5;i++)
    {
        std::cout << v3[i] << " ";
    }
    std::cout << std::endl; 
     std::cout << "4: "; 


//4
    for(int i=0;i<5;i++)
    {
        std::cout << v4[i] << " ";
    }
    std::cout << std::endl; 
     std::cout << "5: "; 


//5
    for(int i=0;i<5;i++)
    {
        std::cout << v5[i] << " ";
    }
    std::cout << std::endl; 
 std::cout << "6: "; 

//6
    for(int i=0;i<5;i++)
    {
        std::cout << v6[i] << " ";
    }
    std::cout << std::endl; 


    v5.swap(v6); 
//重载函数swap
  //交换二者中元素 ;

 std::cout << "7: "; 

//7
    for(int i=0;i<5;i++)
    {
        std::cout << v5 [i] << " ";
    }
    
    std::cout << std::endl; 

     std::cout << "8: "; 
//8    
    for(int i=0;i<5;i++)
    {
        std::cout << v6[i] << " ";
    }
    std::cout << std::endl; 


//size函数 
    int a=v1.size();
  //返回元素的个数; 


    std::cout << a<<std::endl; 

  
  //empty函数  
    int b=v1.empty();

  //判断容器是否为空(为空则返回一) 
     std::cout << b<<std::endl; 
      std::cout <<std::endl; 
        std::cout <<std::endl; 
          std::cout <<std::endl; 
          


    v2.resize(4);
//resize函数重载用法一:
 
 //vector.resize(num);
 
 //这个函数用于重新指定vector容器的长度为num。
 
 //如果新的长度num大于当前容器的长度,那么容器会在末尾添加新的元素,这些新元素会被初始化为该类型的默认值。
 
 //如果新的长度num小于当前容器的长度,那么容器会删除末尾超出新长度的元素。 
    std::cout << "9: "; 
//9
    for(int i=0;i<v2.size();i++)
    {
        std::cout << v2[i] << " ";
    }
    std::cout << std::endl; 
   std::cout <<std::endl; 
     std::cout <<std::endl; 
       std::cout <<std::endl; 
 
    v2.resize(9,100);
//resize函数重载用法二:
 //vector.resize(num, elem);
 //这个函数同样用于重新指定vector容器的长度为num。
 //如果新的长度num大于当前容器的长度,那么容器会在末尾添加新的元素,这些新元素会被初始化为elem的值。
 //如果新的长度num小于当前容器的长度,那么容器会删除末尾超出新长度的元素。
     std::cout << "10: "; 
//10
    for(int i=0;i<v2.size();i++)
    {
        std::cout << v2[i] << " ";
    }
     std::cout <<std::endl; 
       std::cout <<std::endl; 
         std::cout <<std::endl;   std::cout <<std::endl; 
   


//v2.at(100)=5;//防止越界访问时程序终止不报错 ;


    v2.push_back(1);
//push_back函数: 
 //在末尾插入一个元素; 


    v2.push_back(2);
    v2.push_back(3);
    v2.push_back(4);
    v2.pop_back();
//pop_back函数:(无返回值) 
 //删除最末尾的元素 
    
   
   
      std::cout << "11: "; 
//11
    for(int i=0;i<v2.size();i++)
    {
        std::cout << v2[i] << " ";
    }
     std::cout <<std::endl; 
       std::cout <<std::endl; 
       v2.pop_back();
       
       
       
       
       
//***********************//
//insert函数: (多种重载用法) 
 //在指定位置插入一个元素;
    v2.insert(v2.begin()+3,360);
   //注意第一个参数为指针;在v2+3的位置插入一个元素,其他元素依次后移;(.begin取该容器的首地址) 
//12
    puttt(v2); 
//在指定位置插入多个元素
    v2.insert(v2.begin()+5,3,911);
//13
    puttt(v2);
//将指定区间中多个元素插入到指定位置
    v2.insert(v2.begin()+10,v1.begin()+2,v1.end());
 //第一个参数是元素插入的首地址 ,第二个参数为插入元素的首地址,第三个为插入元素的末地址+1(数组直接取数组名)
 //注意:指定区间为前闭后开 
//14
    puttt(v2); 
    
    
    
    
    
    
//迭代器的使用
 //构造一个迭代器对象
    std::vector<int>::iterator it;
 //it=v2.begin();   让迭代器it指向v2的第一个元素 


 //15 
     std:: cout << "15: "; 
    for(it=v2.begin();it!=v2.end();it++)
    {
        std::cout << *it << " ";
     } 
     std::cout << std::endl;

//迭代器的失效
    it=v2.begin()+4;
    v2.insert(it,1234);
    std::cout << *it << std:: endl; 
    
//16    
     std:: cout << "16: "; 
    for(it=v2.begin();it!=v2.end();it++)
    {
        std::cout << *it << " ";
     } 
     std::cout << std::endl;
    
    std::cout << *it << std:: endl; // 野指针 
    
    
    
 //失效原因:插入后是开辟一个新的空间来储存容器;但it还指向原来的地址;在dev中原数据不会被释放,所以输出原数据    
 //解决办法:运用insert的返回值(新的有效的迭代器);
 //it=insert(it,123);//更新迭代器;


//erase函数(vector 
 //作用:两种重载形式,传入一个参数(地址),删除该地址所指向的元素;传入两个参数(地址),删除前闭后开区间内指向的元素 
 //返回值:函数返回一个迭代器。这个迭代器指向最后一个被删除元素之后的元素。
    it=v2.begin()+4;
    it=v2.erase(it,it+6);
    std::cout << *it << std:: endl; 
    
//17    
     std:: cout << "17: "; 
    for(it=v2.begin();it!=v2.end();it++)
    {
        std::cout << *it << " ";
     } 
     std::cout << std::endl;
    
    std::cout << *it << std:: endl;//野指针 
    
    
    
    
    
    
//***********************************************************************************************//

//deque容器

//deque 是双端数组,而 vector 是单端的。 

//deque 在接口上和 vector 非常相似,在许多操作的地方可以直接替换。

//deque 可以随机存取元素(支持索引值直接存取,用 [] 操作符或 at () 方法)。

//deque 头部和尾部添加或移除元素都非常快速,但是在中部安插元素或移除元素比较费时。

//适合在需要频繁在两端进行插入和删除操作的场景中使用,而 vector 更适合在尾部频繁操作以及在中间插入的场景


    std::deque<int> d1={101,102,103,2,3,4};
    std::deque<int>::iterator it2;
//18
    std::cout<<"18: ";
    for(it2=d1.begin();it2!=d1.end();it2++)
    std::cout<< *it2 << " "; 
    std::cout<< std::endl;
    std::cout<< std::endl;
    std::cout<< std::endl;
    
    d1.push_front(100);
//push_front函数
//相较与vector容器多出了对头部元素进行插入的函数 

//19    
    std::cout<<"19: ";
    for(it2=d1.begin();it2!=d1.end();it2++)
    std::cout<< *it2 << " "; 
    std::cout<< std::endl;    
    std::cout<< std::endl;
    std::cout<< std::endl;
    
    
    d1.pop_front(); 
//pop_front函数
//相较与vector容器多出了对头部元素进行删除的函数 

//20   
    std::cout<<"20: ";
    for(int i:d1)
    std::cout<< i << " "; 
//这里使用了范围for循环来遍历myDeque容器中的元素。
//范围for循环的语法形式为for (元素类型 变量名 : 容器名),
//在每次循环时,会自动将容器中的下一个元素赋值给变量(这里是i),然后执行循环体中的代码。
    std::cout<< std::endl;    
    std::cout<< std::endl;
    std::cout<< std::endl;

//***********************************************************************************************//
    
//list容器

//list 是一个双向链表容器,可高效地进行插入和删除元素。(每个节点包含数据和指向前后节点的指针) 

//list 不可以随机存取元素,所以不支持 at (pos) 函数与 [] 操作符。(储存空间非连续) 
//不支持随机访问:由于list是链表结构,不支持通过索引直接访问元素。
//如果要访问list中的某个元素,通常需要从表头或表尾开始遍历,直到找到目标元素。

//在实际应用中,如果需要频繁随机访问元素,vector是更好的选择;
//如果需要频繁在中间进行插入和删除操作,list则更为合适。


/*在 C++ 编程中,list 容器适用于频繁进行插入和删除操作的场景,
但由于其不支持随机存取,在需要按索引访问元素的场景下不适用。(查找与更改的时间复杂度都为o(n)*/

/*例如,如果你需要在一个序列中频繁地在中间插入或删除元素,list 容器会比 vector 容器更高效,
因为 vector 在中间插入或删除元素可能会导致大量元素的移动.*/
    std::list<int> l1={10,15,17,23,10,15};
    l1.push_back(10);
    l1.push_back(20);
    std::list<int> l2(l1);
//21
    std::cout<< "21: "; 
    for (int i : l1)
    {
        std::cout << i << " ";
    }
    std::cout << std::endl;

//操作一:   
//元素存储: 
//l.front()://返回第一个元素。不检查第一个元素是否存在。
//l.back()://返回最后一个元素。不检查最后一个元素是否存在。

//注意:与.begin(),.end()不同,一种返回的是元素本身;一种返回的是地址(.end()返回的是末地址的下一个地址) 


//操作二:   
//元素插入 
//l.insert(pos,e)://在pos(指针)位置插入元素e的副本,并返回新元素位置。
//l.insert(pos,n,e)://在pos位置插入n个元素e的副本。
//l.insert(pos,begin,end)://在pos位置插入区间[begin,?end)内所有元素的副本。
//l.push_back(e)://在尾部添加一个元素e的副本。
//l.push_front(e)://在头部添加一个元素e的副本。
/*与vector相似,不给予演示*/ 
    
    


//操作三:   
//元素的删除与更改 
//**//l.pop_back()://移除最后一个元素。没有返回值。
//**//l.pop_front()://移除第一个元素。没有返回值。
//**//l.erase(pos)://删除pos位置的元素,返回下一个元素的位置。
//**//l.erase(begin,end)://删除区间[begin,end)内所有元素,返回下一个元素的位置。
/*与vector相似,不给予演示*/ 

//提示:erase的不当运用也会出现迭代器的失效,应当运用其返回值灵活解决; 

//**//l.remove(val)://移除所有值为val的元素。
    l1.remove(15);
    

//22
    std::cout<< "22: "; 
    for (int i : l1)
    {
        std::cout << i << " ";
    }
    std::cout << std::endl;


//**//l.remove_if(op)://移除所有满足“op(val)==true”的元素。
    l1.remove_if(shi);
    
//23
    std::cout<< "23: "; 
    for (int i : l1)
    {
        std::cout << i << " ";
    }
    std::cout << std::endl;

//l.clear()://移除所有元素,清空容器。
//l.resize(num)://将元素数量改为num(增加的元素用默认构造函数产生,多余的元素被删除)。
//l.resize(num,e)://将元素数量改为num(增加的元素是e的副本)。


  
//其他操作

//l.unique()://移除重复元素。
    l2.unique();
        
//24
    std::cout<< "24: "; 
    for (int i : l2)
    {
        std::cout << i << " ";
    }
    std::cout << std::endl;
//l.unique(op)://移除满足“op(val)==true”的重复元素。


//list 特有函数splice
//std::list 容器提供了几个不同重载形式的 splice 函数,
//其主要功能是将一个 list 中的元素移动到另一个 list 的指定位置,这个操作是高效的,
//因为它只是调整链表节点的指针,不会涉及元素的复制或删除(除非有相关的析构等操作)。 
 
    
    
    
//l1.splice(pos,l2)://将l2内的所有元素转移到l1的迭代器之前。    
    l1.splice(l1.end(), l2);
    // 此时 list1 变为 {1, 2, 3, 4, 5, 6},list2 变为空
           
//25
    std::cout<< "25: "; 
    for (int i : l1)
    {
        std::cout << i << " ";
    }
    std::cout << std::endl;


//l1.splice(pos,l2,l2pos)://将l2内l2pos所指元素转移到l1内的pos之前。
//注意:是转移到该位置之前 
//l1.splice(pos,l2,l2begin,l2end)://将l2内[l2begin,l2end)区间内所有元素转移到l1的pos之前。
    l2.splice(l2.end(),l1,l1.begin()); 
               
//26
    std::cout<< "26: "; 
    for (int i : l2)
    {
        std::cout << i << " ";
    }
    std::cout << std::endl;

//l.sort()://以operator<为准则对所有元素排序。
//l.sort(op)://以op(定义“小于”关系)为准则对所有元素排序。
//l1.merge(l2)://假设l1和l2都已排序,将l2全部元素转移到l1并保证合并后仍是有序表。
//l.reverse()://将所有元素反序

      
     

//list的反向迭代器
//27
    std::cout << "27: ";
    list<int>::reverse_iterator it3;
    for(it3=l1.rbegin();it3!=l1.rend();it3++)
    {
        std::cout << *it3 << " ";
     } 
    std::cout << std::endl;
//rend()返回的也是首地址的前一位; 
//提示:it++ 迭代器自增自减操作是可行的;it + 5 迭代器加一个整数操作是不可行的。 
    
    
    
    
    
//***********************************************************************************************//
    
//stack容器
//stack(栈)是 C++ 标准模板库(STL)中的一种容器适配器。它遵循后进先出(LIFO - Last In First Out)的原则,
//就像一摞盘子,最后放上去的盘子最先被拿走。stack主要用于需要这种特殊访问顺序的场景,
//比如函数调用栈(在程序运行时,函数调用的顺序和返回顺序符合栈的特性)、表达式求值(如后缀表达式求值)等。 
    
    stack<int> st1;
    st1.push(1);
    st1.push(2);
    st1.push(7);
    st1.push(4);
    st1.push(8);
    st1.push(1);
    st1.push(11);
    
    cout << st1.top()<<endl;
//top返回栈顶元素,不会删除;
    stack<int> st2(st1);//调用拷贝构造函数 
    stack<int> st3=st1;//调用拷贝构造函数 
    stack<int> st4;
    st4=st1;//调用=重载 

    st1.pop();
//出栈,删除栈顶元素 
    cout << st1.top()<< " "<< st1.size()<<endl;
//stack容器 没有迭代器,不允许遍历; 

//28
    cout<< "28: "; 
    while(st1.empty()!=1)
    {
        cout<<st1.top()<< " "; 
        st1.pop(); 
     } cout<< endl; 
     
     
//***********************************************************************************************//
    
    
    
//queue容器
//queue(队列)是 C++ 标准模板库(STL)中的容器适配器
//它遵循先进先出(FIFO - First In First Out)的原则。可以把它想象成一个排队的队伍,先进入队伍的元素先离开。
//这种数据结构在很多场景中都非常有用,例如任务调度、广度优先搜索(BFS)算法等。 
    
    queue<int> q1;
     q1.push(1);
     q1.push(2);
    q1.push(7);
    q1.push(4);
    q1.push(8);
    q1.push(1);
    q1.push(11);
    
    
    
    cout << q1.front()<<endl;
//获取队头元素 
    cout << q1.back()<<endl;
//获取队尾元素 
//拥有pop,size,empty的调用 
//用法,函数都大致与stack相似,不一一赘述; 
    
    
//***********************************************************************************************//


//set和multiset容器
//set存储的元素是唯一的并且按照特定的顺序(默认是升序)排列 
//插入与删除更快
//所有存进去的元素都是有序的,不能指定插入位置;
//正向反向迭代器都有 
/*set容器与multiset容器的区别在于set支持唯一键值,每个元素值只能出现一次
而multiset中同一值可以出现多出*/
//set容器不支持修改一个元素值,只能删除再插入; 
    
    set<int > s1;
//set<int,greater<int>>是按升序排列,默认为降序排列 
//set<int,less<int>>是降序排列,等于set<int> 
    s1.insert(5);
    s1.insert(2);
    s1.insert(5);
    s1.insert(8);
    s1.insert(8);
    s1.insert(0);
    s1.insert(-4);
    s1.insert(775);
    set<int>::iterator it4;
    
//29
    cout << "29: ";
    for(it4=s1.begin();it4!=s1.end();it4++)
    {
        cout << *it4 << " ";
     } cout <<endl;

    set<int>:: reverse_iterator it5;
//30     
     cout << "30: ";
    for(it5=s1.rbegin();it5!=s1.rend();it5++)
    {
        cout << *it5<< " ";
    }cout << endl;
    
    
    
//find(elem)函数 ,查找elem,返回elem的迭代器 
//31
    cout << "31: ";
    for(it4=s1.find(2);it4!=s1.end();it4++)
    {
         cout << *it4 << " ";
    } cout << endl;


//count(elem)函数 返回elem的元素个数 
//lower_bound(elem)函数 返回第一个>=elem元素的迭代器 
//uper_bound(elem)函数     返回第一个<=elem元素的迭代器 (用于降序set)
    
//***********************************************************************************************//
//pair模板类
//pair是一个模板类,用于将两个不同类型的值组合成一个单一的对象    
//pair提供了一种简单的方式来处理具有两个关联值的情况,比如在一个函数需要返回两个值,
//或者在容器(如map)中存储键 - 值对时非常有用。
    pair<int,double> p1(10,0.1);
    cout << p1.first << " : "<< p1.second <<endl; 
    
//***********************************************************************************************//
    


//map容器
//map 存储的元素是键 - 值对,并且会根据键(key)自动进行排序 
//存的是一对一对的对组 

    map<int,string > m1;
//map 的插入
      
//map.insert(pair<typ,typ>(key, value));或者map.insert({key, value});
      m1.insert(pair<int,string>(1, "oo"));
//还可以直接构造一个pair p<int,int>(key,value); 插入p; 
    m1.insert({2, "tt"});
//map[key] = value;
    

//注意,使用 map[key] = value当map内存在一个相同的键值的时候,会覆盖掉这个键值
//而第一种方法不会;所以一般提倡使用第一种;(防止误伤) 


    m1[3]="th"; //([]的重载) 
    m1.insert(pair<int,string>(1, "ob"));
    m1[3]="tw";
//map的迭代器的使用  
    map<int,string>::iterator it6;
    for(it6=m1.begin();it6!=m1.end();it6++)
    {
        pair<int ,string> pr=*it6;
        cout <<  pr.first << ": "<< pr.second<<endl;
     } 
//用键值对map中元素进行查找; 
//find(elem)函数,返回第一个elem键值所对应的迭代器;
//如果找不到则返回find.end(); 
    it6=m1.find(2);


    pair<int ,string> pi=*it6;


    cout <<  pi.first << ": "<< pi.second<<endl;

//使用map[i]进行访问(提示:如果不存在则创建一个键为i的键值对,默认值是" ";
//应当谨慎使用; 
            
    return 0;
 } 

### 关于C++ STL的Markdown格式笔记教程 以下是关于C++ STL(Standard Template Library)的一个完整的Markdown格式笔记教程,涵盖了STL的主要组成部分及其基本用法。 #### 1. STL概述 C++的标准模板STL)是一个强大的工具集,主要由容器、算法和迭代器组成[^1]。这些组件通过迭代器相互协作,提供了高效的数据结构和操作方法。 --- #### 2. 容器 (Container) 容器是用来存储数据的对象集合。STL中的容器可以分为三类:序列式容器、关联式容器以及无序关联式容器。 ##### 序列式容器 - **`vector`**: 动态数组,支持随机访问。 ```cpp #include <iostream> #include <vector> using namespace std; int main() { vector<int> vec = {1, 2, 3}; for(auto& num : vec){ cout << num << " "; } return 0; } ``` - **`list`**: 双向链表,适合频繁插入删除操作。 ```cpp #include <iostream> #include <list> using namespace std; int main(){ list<int> lst = {1, 2, 3}; lst.push_back(4); for(auto& num : lst){ cout << num << " "; } return 0; } ``` ##### 关联式容器 - **`set`**: 存储唯一键值并按升序排列。 ```cpp #include <iostream> #include <set> using namespace std; int main(){ set<int> st = {3, 1, 2}; for(auto& num : st){ cout << num << " "; // 输出为1 2 3 } return 0; } ``` - **`map`**: 键值对存储,并按键排序。 ```cpp #include <iostream> #include <map> using namespace std; int main(){ map<string, int> mp = {{"语文", 97}, {"数学", 82}}; for(auto& pair : mp){ cout << pair.first << ": " << pair.second << endl; } return 0; } ``` ##### 无序关联式容器 - **`unordered_set`**: 不按键排序,基于哈希表实现。 - **`unordered_map`**: 基于哈希表实现的键值对存储方式[^3]。 ```cpp #include <iostream> #include <unordered_map> using namespace std; int main(){ unordered_map<string, int> umap = {{"体育", 55}, {"语文", 97}}; for(auto& pair : umap){ cout << pair.first << ": " << pair.second << endl; } return 0; } ``` --- #### 3. 迭代器 (Iterator) 迭代器是一种通用化的指针,用于遍历容器中的元素。可以通过不同的方式进行元素访问[^4]。 ```cpp #include <iostream> #include <vector> using namespace std; int main(){ vector<int> vec = {1, 2, 3}; vector<int>::iterator it = vec.begin(); while(it != vec.end()){ cout << *it << " "; ++it; } return 0; } ``` --- #### 4. 算法 (Algorithm) STL提供了一系列高效的泛型算法,可以直接作用于各种容器之上。 - **排序** ```cpp #include <algorithm> sort(vec.begin(), vec.end()); ``` - **查找** ```cpp bool found = binary_search(vec.begin(), vec.end(), value); ``` - **变换** ```cpp transform(vec.begin(), vec.end(), result.begin(), [](int i){return i*2;}); ``` --- ### 总结 以上是对C++ STL核心概念的一次总结性介绍,包括容器、迭代器和算法等内容。每部分内容都附有简单的代码示例以便理解[^1]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值