C++容器自结

C++ STL库 容器自我小结

Vector容器

  1. 初始化

    (1)构造函数初始化

    vector<int> vecname(size,initval);
    

    注:size和initval两个参数都可以省略,缺省值均为0.

    vector<int> a;//初始化一个size为0的vector
    vector<int> aa(10);//初始化了一个size为10且值全为0的vector
    vector<int> aaa(10,1);//初始化了一个size为10且值全为1的vector
    

    (2)通过同类型vector初始化

    vector<int> a(10,2);
    vector<int> b(a);
    

    (3)通过insert()函数初始化

    vector<int> a(6,6);
    
    vector<int> b;//首先要声明一个vector容器
    b.insert(b.begin(),a.begin(),a.begin()+3);
    //vec1.insert(insertpos,startpos,endpos);
    //在vec1的inserpos位置中插入[starpos,endpos)中的值
    //注意区间的前开后闭,以及三个pos值都是以迭代器形式给出
    
    vector<int> a(6,6);
    
    vector<int> b;//首先要声明一个vector容器
    b.insert(b.begin(),5,8);
    //vec.insert(insertpos,nums,val);
    //在vec的insertpos位置中插入nums个值为val的元素
    //insertpos同样是迭代器类型
    

    (4)二维vector的初始化

    ①vec.resize()方法

    vector<vector<int> > a;
    a.resize(m);//对外层vector进行大小初始化,也就是有m行
    
    //因为vector容器的特性,vector中的各行大小不一定完全确定,可以在循环中分别初始化
    
    for(int i = 0;i<m;i++)
        a[i].resize(ni);//ni表示第i行应该具有的元素个数
    

    ②初始化函数

    vector<vector<int> > aa(m,vector<int>(n,vals));
    //这个格式和一维vector初始化有点类似
    //aa被初始化为一个mxn的二维数组,初始值为vals
    

Map容器

  1. 基本介绍

    map是STL的一个关联容器提供关键字和值的一对一数据处理能力。map内部自建一棵红黑树,这棵树具有对数据的自动排序功能,所以在map内部所有的数据都是有序的。

  2. 初始化、构造与常用方法

    map<typename1,typename2> mapname;
    mapname.size();//数据数目
    mapname.empty();//判空
    mapname.clear();//清空map中的数据
    
  3. 数据插入

    (1)使用insert函数插入数据

    //插入pair数据
    map<int,int> mp;
    mp.insert(pair<int,int>(1,2));//使用pair构造方法
    mp.insert(make_pair(1,2));//使用make_pair构造函数
    
    //插入value_type数据
    mp.insert(map<int,int>::value_type(1,2));
    

    用insert函数插入数据时,在数据的插入上涉及到集合的唯一性概念。即:当map中有这个关键字的时候,insert操作就无法再插入这组数据。

    (2)用数组方式插入数据

    map<int,int> mp;
    mp[1] = 2;
    

    但是用数组方式进行插入,如果有相同的关键字,后面插入的数据会覆盖该关键字对应的值。

  4. 数据遍历

    map<int,int> mp;//注意后面构造迭代器时类型要一致
    
    //使用前迭代器
    for(map<int,int>::iterator it = mp.begin();it!=mp.end();it++){
        //遍历操作
    }
    
    //使用反相迭代器
    for(map<int,int>::iterator it = mp.rbegin();it != mp.rend();it++){
        //遍历操作
    }
    
    //使用数组方式
    for(int i = 0;i<mp.size();i++){
        cout<<mp[i];
    }
    
  5. 数据的查找

    //使用count函数确定某一个关键字是否出现
    map<int,int> mp;
    if(mp.count(1))
        cout<<"1是该map中的一个键值"<<endl;
    
    //使用find函数定位数据出现的位置
    if(mp.find(1)!=mp.end())
        cout<<"1是该map中的一个键值"<<endl;
    

    count函数的返回值只可能是0或1,当返回值为1的时候即说明该关键字出现。

    find函数返回的是数据所在位置的迭代器,如果map中没有需要查找的数据的话,就返回end函数指向的迭代器。

  6. 数据删除

    //数据的删除使用erase函数,它具有三种重载形式,注意参数
    
    map<int,int> mp;
    // Type1:使用迭代器进行元素删除
    map<int,int>::iterator it = mp.find(1);
    mp.erase(it);//常借助find函数找到某一元素的迭代器
    
    //Type2:使用关键字进行元素删除
    mp.erase(1);
    
    //Type3:使用迭代器删除多个元素
    mp.erase(mp.begin(),mp.end());//等价于mp.clear()
    //注意stl的特性,区间表示都是前闭后开
    

Set容器

  1. 基本介绍

    set用来存储同一数据类型,能针对一个数据集合中进行增、删、查的操作;在set中每个元素的值都唯一,系统可以根据元素的值自动进行排序。

    set也是C++ STL中的标准关联容器(还有map,multiset,multimap),其内部采用红黑树的数据结构。

    • 因为不需要做内存拷贝和内存移动,所以map和set的插入和删除操作的效率更高。
    • 因为内存没有发生改变 ,所以进行insert操作之后set的iterator不会失效,使用find()相关算法时不用担心过期的iterator问题。
    • 因为底层是高效的树结构且set采用的是二分查找,所以随着数据元素的增多,set的插入和查找速度仅仅呈现对数级增长。
  2. 声明与初始化

    set<typename> setname;
    
  3. 常用函数与属性

    set<int> st;
    //返回set容器的始末元素的迭代器
    st.begin(),st.end();
    //清空set容器
    st.clear();
    //判空,返回为真值说明为空
    st.empty();
    //当前容器内含有的元素个数
    st.size();
    //声明时设置的可能包含的元素的最大个数
    st.max_size();
    //反向迭代器的始末位置
    st.rbegin(),st.rend();
    //某一元素出现的次数,因为set的特性返回值只可能是0或1
    st.count(1);//1在st中出现的次数
    //查找某一给定值的定位器,未找到则返回end()
    st.find(1);//常利用st.find(nums)!=st.end()判断nums是否存在
    
  4. 插入元素

    //使用insert函数,注意不同的重载形式
    set<int> st;
    //插入某一元素值,返回pair<set<int>::iterator,bool>
    st.insert(1);//将1插入到集合中
    
    //插入定位器start到final之间的元素,无返回值
    int a[] = {2,3,4,5};
    st.insert(a,a+3);
    //数组名称可以直接表示地址
    
    vector<int> a(10);
    st.insert(a.begin(),a.begin()+3);
    //假设已经对内部元素进行过插入
    
  5. 删除元素

    //使用earse()函数,同样注意重载形式
    
    set<int> st;
    //删除某一键值
    st.erase(1);//删除元素1
    
    //删除定位器指向的元素
    st.erase(st.begin());//删除集合中最小的元素,"自动排序"
    
    //删除定位器start到final之间的元素
    set<int>::iterator final = st.begin();
    final++;//只用string和vector的迭代器可以用it+num的形式
    final++;
    st.erase(st.begin(),final);//删除前两个元素
    
  6. 元素定位器

    set<int> st;//假设该集合中有1,2,3,4共四个元素
    
    //返回第一个大于等于key_value的定位器
    st.lower_bound(2);//第一个≥2的定位器
    
    //返回最后一个大于等于key_value的定位器
    st.upper_bound(2);//最后一个≥2的定位器
    

String 容器

  1. 声明与初始化

    string str;//声明一个空字符串
    
    //用已知的string对象初始化
    string s(str);
    
    //用已知的string对象的某一位置开始的某个长度的字串初始化
    string s(str,str.begin(),str.size());
    
    //初始化为若干个相同的字符
    string s(10,'a');
    
    //用已知的string对象从某一下标开始到结束的字串初始化
    string s(str,str.begin());
    
    //注意下标从0开始
    
    
  2. 常用方法和属性

    //string对象含有的字符个数
    string.size();
    string.length();
    
    //string对象最多可以包含的字符个数,跟对象封装有关
    string.max_size();
    
    //重新分配内存之前,string对象能包含的最大字符数;跟当前内存分配有关
    string.capacity();
    
    //正向迭代器
    string str;
    string::iterator it = str.begin();//str.end()
    
    //反向迭代器
    string str;
    string::reverse_iterator rit = str.rbegin();//str.rend()
    
    //字符串排序,按照字典序排列
    string str;
    sort(str.begin(),str.end());
    
  3. 字符的插入

    //使用push_back()方法尾插字符
    string s1;
    s1.push_back('a');
    s1.push_back('b');//s1:ab
    
    //使用insert方法在指定位置插入字符
    string s2;//假设s2:ab
    s2.insert(s2.begin(),'c');//s2:cab
    
    
  4. 字符串的比较

    // 1. 使用比较操作符,可以按照字典序直接对两个字符串对象比较
    
    //2. 成员函数compare()
    /* str1.compare(id1,len1,str2,id2,len2);
    str1的id1处开始长度为len1的子串与str2的id2开始长度为len2的子串进行比较,id和len的参数缺省则默认是两个字符串str1和Str2进行比较
    */
    string A("123456");
    string B("123dfg");
    A.compare(0,3,B,0,3);//“123”和“123”的比较
    
  5. 字符串的拼接

    // 1. 使用+运算符
    string str1("123");
    string str2("456");
    str1 += str2;//str2:123456
    
    //2. 使用append方法
    string str1("123");
    str1.append("def");//str1:123def
    
  6. 字符串的删除

    //字符串的清空
    string.clear();
    
    //使用erase()函数,注意重载形式
    
    //1. 清除定位器所指向的字符
    string str("123456");
    str.erase(str.begin());//str:23456
    
    //2. 清除定位器[start,final)之间的字符,字符串迭代器可以使用it+num的形式
    string str("123456");
    str.erase(str.begin(),str.begin()+2);//str:3456
    
    //3. 清除字符串从某一pos开始长度为len的子串
    string str("123456");
    str.erase(0,2);//str:3456
    
  7. 字符串的查找

    //1. find()函数,p.s. find()与rfind()得到区别在于从前还是从后开始查找
    string str("123456123456");
    str.find("23");//查找某一字串的首字符在源串的下标
    str.find("23",0);//查找从下标0开始找到的第一个“23”子串的下标
    
    //2. 在源串中找某一个子串中的字符
    string str("123456");
    str.find_first_of("ab3r67");//查返回"ab3r67"中第一个在str中出现的字符的下标  3---返回2
    
    

Stack容器

  1. 基础知识

    ①堆栈本质上也是一个线性表,只不过操作受到限制——插入和删除操作只在表的一端进行:堆栈是一个后进先出(LIFO)的表格。

    ②C++ STL中的堆栈泛化是直接通过现有的序列容器来实现的,默认使用双端队列,可以改成其他的线性结构。

    ③为了严格遵循堆栈中数据的后进先出原则,stack不提供元素的任何迭代器操作——stack容器不会像外部提供可用的前向或反向迭代器类型。

  2. 声明与初始化

    stack<typename> sname;
    
  3. 常用方法与属性

    //stack容器是对栈的实现,元素满足后进先出的特性
    stack<int> st;
    //将元素压入堆栈的栈底
    st.push(1);
    
    //将元素从栈顶取出,并不会返回元素的值
    st.pop();
        
    //在队列非空时取栈顶的元素
    int head = st.top();//栈顶元素
    
    //堆栈元素的总数
    int sum = st.size();
    
    //判断堆栈容器是否为空
    st.empty();
    

Queue容器

  1. 声明与初始化

    queue<typename> qname;
    
  2. 常用方法与属性

    //queue容器是对队列的实现,元素满足先进先出的特性
    queue<int> q;
    //将元素放入队列末尾
    q.push(1);
    
    //将元素从队列头部取出,并不会返回元素的值
    q.pop();
        
    //在队列非空时取队列中队首或者队尾的元素
    int head = q.front();//队首元素
    int tail = q.back();
    
    //队列元素的总数
    int sum = q.size();
    
    //判断队列容器是否为空
    q.empty();
    
  3. 优先队列(priority_queue)

    (1)基本介绍

    priority_queue是定义在queue头文件内的一个有用的模板类,队列容器是按照入队的先后顺序出队;但是优先队列是按照队列内的元素的优先权进行出队的(模板的默认值是元素值越大,优先权就越大),也可以指定算子来改变默认的优先顺序。

    priority_queue模板类中有三个模板参数——元素类型、容器类型、比较算子。后两个可以省略,在模板的默认值下是vector和less算子。

    p.s. 算子决定了元素在优先队列中的排列顺序,也就是less的作用下小元素排列在队列的前面,元素大的则后置。

    但是优先队列出队的时候是从队列末尾开始弹出元素——也就是,在less算子的作用下,元素值越大的元素优先权越大(优先弹出队列)

    (2)对象声明与定义

    priority_queue<int> pq1;//后两项缺省,整型数值越大的元素其优先权越大
    
    priority_queue<pair<int,int> > pq2;//改变元素类型
    
    priority_queue<int,vector<int>,greater<int> > pq3;
    //显式写出了元素类型和容器类型,以及改写了默认比较算子
    

    (3)自定义比较算子

    • 如果是基本的数据类型,可以直接使用模板中提供的greater和less算子
    • 若要自定义比较算子,其中一种方法就是重载运算符
    //以下自定义一个结构类,并针对这个结构类重载运算符
    
    class node{
        public:
            int x,y,z;
            node(int a,int b,int c){}
    };
    bool operator<(const node& n1,const node& n2){
        return n1.z<n2.z;//按照结构中z分量增序排序,值越大的优先权越大
    }
    
    //测试程序
    int main(void)
    {
    	priority_queue<T>q;
    	q.push(T(4,4,3));
    	q.push(T(2,2,5));
    	q.push(T(1,5,4));
    	q.push(T(3,3,6));
    	while(!q.empty())
    	{
    		T t=q.top();
    		q.pop();
    		cout<<t.x<<" "<<t.y<<" "<<t.z<<endl;
    	}
    	system("Pause");
    	return 1;
    }
    

其他小Tips

  1. 重写比较函数

    在使用sort函数还有优先队列重写优先级逻辑的时候会用得到。

    struct cmp{
        bool operator()(typename &para1,typename &para2){
            return f(para1) < f(para2);
        }
    };
    
    func(){
        //函数其他主体内容
        sort(iterator1,iterator2,cmp());//sort函数中调用
        priority_queue<elemtype,containertype,cmp()>;
        //优先队列定义的时候使用,优先队列就会按照重写的逻辑进行元素处理
    }
    
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值