C++ STL容器解读

1.vector向量容器
    vector向量容器不但能像数组一样对元素进行随机访问,还能在尾部插入元素,是一种简单、高效的容器,完全可以代替数组。vector具有内存自动管理的功能,对于元素的插入
和删除,可动态调整所占的内存空间。vector容器的下标是从 0开始计数的,也就是说,如果vector容器的大小是 n,那么,元素的下标是0~n-1。对于vector容器的容量定义,
可以事先定义一个固定大小,事后,可以随时调整其大小;也可以事先不定义,随时使用push_back()方法从尾部扩张元素,也可以使用insert()在某个元素位置前插入新元素。
vector容器有两个重要的方法,begin()end()begin()返回的是首元素位置的迭代器;end()返回的是最后一个元素的下一元素位置的迭代器。
1.1创建vector对象:
    vector<int>v;vector<double> v(10);vector<double> v(10,8.6);
1.2尾部元素扩张:使用push_back()vector
        容器在尾部追加新元素。尾部追加元素,vector容器会自动分配新内存空间。可对空的 vector对象扩张,也可对已有元素的vector对象扩张。
1.3访问或遍历vector对象是常要做的事情。
        对于 vector对象,可以采用下标方式随意访问它的某个元素,当然,也可以以下标方式对某元素重新赋值,这点类似于数组的访问方式。
1.4用迭代器访问vector元素:
        常使用迭代器配合循环语句来对vector对象进行遍历访问,迭代器的类型一定要与它要遍历的vector对象的元素类型一致。
    vector<int>::iteratorit;
1.5元素的插入:
    insert()方法可以在vector对象的任意位置前插入一个新的元素,同时,vector自动扩张一个元素空间,插入位置后的所有元素依次向后挪动一个位置。
    insert()方法要求插入的位置,是元素的迭代器位置,而不是元素的下标。
    v.insert(it,int);
1.6元素的删除
    erase()方法可以删除vector中迭代器所指的一个元素或一段区间中的所有元素。clear()方法则一次性删除vector中的所有元素。
    v.erase(it1it2);删除迭代器第it1到第it2区间的所有元素。
1.7使用reverse反向排列算法
    reverse算法可将向量中某段迭代器区间元素反向排列.
    reverse(it1,it2);//反向排列向量的从it1it2的元素
1.8使用sort算法对向量元素排序
        使用 sort算法,需要声明头文件“#include<algorithm>”sort
        算法要求使用随机访问迭代器进行排序,在默认的情况下,对向量元素进行升序排列.
    sort(it1,it2);//排序,升序排列
    sort(it1,it2,Comp);//Comp函数比较规则排序
1.9向量的大小
        使用 size()方法可以返回向量的大小,即元素的个数。
        使用 empty()方法返回向量是否为空。
    v.empty()//输出向量是否为空,如果非空,则返回逻辑假,0,否则返回逻辑真,1
 
 


2.string基本字符系列容器
C++STL提供了 string基本字符系列容器来处理字符串,可以把string理解为字符串类,它提供了添加、删除、替换、查找和比较等丰富的方法。
2.1创建string 对象
    string s;
2.2string对象赋值
    string s;
    s="hello,C++STL.";

        把字符指针赋给一个字符串对象:   
    charss[5000];
    s=ss;//把整个字符数组赋值给string 对象
2.3string对象尾部添加字符
string对象的尾部添加一个字符(char),采用“+”操作符即可.
2.4string对象尾部追加字符串
        从尾部追加的方式有两种:(1)直接采用“+”操作符。(2)采用append()方法。
2.5string对象插入字符可以使用 insert()方法把一个字符插入到迭代器位置之前
    s.insert(it,'p');//把字符'p'插入到第 it位置之前
2.6访问string对象的元素
        一般使用下标方式随机访问 string对象的元素,下标是从0开始计数的。另外,string对象的元素是一个字符(char),这点一定要清楚。
2.7删除string对象的元素
    (1)清空一个字符串,则直接给它赋空字符串即可。
    (2)使用erase()方法删除迭代器所指的那个元素或一个区间中的所有元素。
    s.erase(it1,it2);//删除it1~it2区间的所有元素
    s.erase(it);//删除第it位置元素
2.8返回string对象的长度
        采用 length()方法可返回字符串的长度;采用empty()方法,可返回字符串是否为空,如果字符串为空,则返回逻辑真,1,否则,返回逻辑假,0
2.9替换string对象的字符
        使用 replace()方法可以很方便地替换string对象中的字符.
    s.replace(n,m,"good");//从第n个开始,将连续的m个字符替换为“good”
2.10搜索string对象的元素或子串
       采用find()方法可查找字符串中的第一个字符元素(char,用单引号界定)或者子串(用双引号界定),如果查到,则返回下标值(0开始计数),如果查不到,则返回4294967295
2.11string对象的比较
    string对象可与使用 compare()方法与其他字符串相比较。如果它比对方大,则返回1;如果它比对方小,则返回-1;如果它与对方相同(相等),则返回0
2.12reverse反向排序 string对象
        采用 reverse()方法可将string对象迭代器所指向的一段区间中的元素(字符)反向排.reverse()方法需要声明头文件“#include<algorithm>”
2.13string 对象作为 vector元素
    string对象可以作为 vector向量的元素,这种用法,类似于字符串数组。
2.14string 类型的数字化处理
2.15string 对象与字符数组互操作
2.16string 对象与 sscanf函数
C语言中,sscanf函数很管用,它可以把一个字符串按你需要的方式分离出子串,甚至是数字。
    sscanf("abc123 pc","%s %s %s",sa,sb,sc);//将字符串分离成子串,分隔符为空格
    sscanf("1 2 3","%d %d %d",&a,&b,&c);//当用到数字的时候,scanf一样,它要传指针地址
    sscanf("4,5$6","%d,%d$%d",&x,&y,&z);//将字符串分离成数字,分隔符为“,”和“$”,当用到数字的时候,scanf一样,它要传指针地址
2.17string 对象与数值相互转换
 
 
 
 
3.set集合容器
set集合容器实现了红黑树(Red-BlackTree)的平衡二叉检索树的数据结构,在插入元素时,它会自动调整二叉树的排列,把该元素放到适当的位置,以确保每个子树根节点的
键值大于左子树所有节点的键值,而小于右子树所有节点的键值;另外,还得确保根节点左子树的高度与右子树的高度相等,这样,二叉树的高度最小,从而检索速度最快。要注意
的是,它不会重复插入相同键值的元素,而采取忽略处理。对于 set容器中的键值,不可直接去修改。因为如果把容器中的一个键值修改了,set容器会根据新的键值旋转子树,
以保持新的平衡,这样,修改的键值很可能就不在原先那个位置上了。换句话来说,构造set集合的主要目的就是为了快速检索。multiset(多重集合容器)map(映照容器)
multimap(多重映照容器)的内部结构也是平衡二叉检索树。
3.1创建 set集合对象
        创建 set对象时,需要指定元素的类型,这一点与其他容器一样。
3.2元素的插入与中序遍历
        采用insert()方法把元素插入集合中去,插入的具体规则在默认的比较规则下,是按元素值由小到大插入,如果自己指定了比较规则函数,则按自定义比较规则函数插入。
使用前向迭代器对集合中序遍历,其结果正好是元素排序的结果。
3.3元素的反向遍历
         使用反向迭代器 reverse_iterator可以反向遍历集合,输出的结果正好是集合元素的反向排序结果。它需要用到rbegin()rend()两个方法,它们分别给出了反向遍历的
开始位置和结束位置。
3.4元素的删除
        与插入元素的处理一样,集合具有高效的删除处理功能,并自动重新调整内部的红黑树的平衡。
       删除的对象可以是某个迭代器位置上的元素、等于某键值的元素、一个区间上的元素和清空集合。
3.5元素的检索
        使用find()方法对集合进行搜索,如果找到查找的键值,则返回该键值的迭代器位置,否则,返回集合最后一个元素后面的一个位置,end()
3.6自定义比较函数
使用insert()将元素插入到集合中去的时候,集合会根据设定的比较函数将该元素放到该放的节点上去。在定义集合的时候,如果没有指定比较函数,那么采用默认的比较函数,
即按键值由小到大的顺序插入元素。在很多情况下,需要自己编写比较函数。编写比较函数有两种方法。
    (1)如果元素不是结构体,那么,可以编写比较函数。
    (2)如果元素是结构体,那么,可以直接把比较函数写在结构体内。
 
 


4.multiset 多重集合容器
    multisetset一样,也是使用红黑树来组织元素数据的,唯一不同的是,multiset允许重复的元素键值插入,set则不允许。
    multiset也需声明头文件包含“#include<set>”,由于它包含重复元素,所以,在插入元素、删除元素、查找元素上较set 有差别。
4.1multiset 元素的插入
    ms.insert("");
4.2multiset 元素的删除
         采用 erase()方法可以删除multiset对象中的某个迭代器位置上的元素、某段迭代器区间中的元素、键值等于某个值的所有重复元素,并返回删除元素的个数。
        采用clear()方法可以清空元素。
    n=ms.erase("a");//删除值为“a”的所有重复元素,返回删除元素总数n
4.3查找元素
        使用find()方法查找元素,如果找到,则返回该元素的迭代器位置(如果该元素存在重复,则返回第一个元素重复元素的迭代器位置);如果没有找到,则返回end()迭代器位置。
 
 


5.map 映照容器
    map映照容器的元素数据是由一个键值和一个映照数据组成的,键值与映照数据之间具有一一映照的关系。
    map映照容器的数据结构也是采用红黑树来实现的,插入元素的键值不允许重复,比较函数只对元素的键值进行比较,元素的各项数据可通过键值检索出来。由于map set
采用的都是红黑树的数据结构,所以,用法基本相似。
5.1map 创建、元素插入和遍历访问
        创建 map对象,键值与映照数据的类型由自己定义。在没有指定比较函数时,元素的插入位置是按键值由小到大插入到黑白树中去的,这点和set 一样。
5.2删除元素
set容器一样,map映照容器的erase()删除元素函数,可以删除某个迭代器位置上的元素、等于某个键值的元素、一个迭代器区间上的所有元素,当然,
也可使用clear()方法清空map 映照容器。
5.3元素反向遍历
        可以使用反向迭代器 reverse_iterator反向遍历 map照映容器中的数据,它需要rbegin()方法和rend()方法指出反向遍历的起始位置和终止位置。
5.4元素的搜索
       使用 find()方法来搜索某个键值,如果搜索到了,则返回该键值所在的迭代器位置,否则,返回end()迭代器位置。由于map采用黑白树数据结构来实现,所以搜索速度是极快的。
5.5自定义比较函数
       将元素插入到 map中去的时候,map会根据设定的比较函数将该元素放到该放的节点上去。在定义map的时候,如果没有指定比较函数,那么采用默认的比较函数,
即按键值由小到大的顺序插入元素。在很多情况下,需要自己编写比较函数。
      编写比较函数与 set比较函数是一致的,因为它们的内部数据结构都是红黑树。编写方法有两种。
   (1)如果元素不是结构体,那么,可以编写比较函数。
   (2)如果元素是结构体,那么,可以直接把比较函数写在结构体内。
5.6map实现数字分离
      对数字的各位进行分离,采用取余等数学方法操作是很耗时的。而把数字当成字符串,使用map的映照功能,很方便地实现了数字分离。
5.7数字映照字符的 map
写法
将数字映射为相应的字符
#include
<map>
#include
<string>
#include
<iostream>
using
namespace std;
int
main(int argc, char* argv[])
{
//定义
map
对象,当前没有任何元素
map<int,char>
m;
//赋值:字符映射数字
m[0]='0';
m[1]='1';
m[2]='2';
m[3]='3';
m[4]='4';
m[5]='5';
m[6]='6';
m[7]='7';
m[8]='8';
m[9]='9';
/*上面的10条赋值语句可采用下面这个循环来简化代码编写
for(int
j=0;j<10;j++)
{
m[j]='0'+j;
}
*/
int
n=7;
string
s="The number is ";
cout<<s
+ m[n]<<endl;
return
0;
}
 
 


6.multimap 多重映照容器
    multimapmap基本相同,唯独不同的是,multimap允许插入重复键值的元素。由于允许重复键值存在,所以,multimap的元素插入、删除、查找都与 map不相同。
6.1multimap 对象创建、元素插入
         可以重复插入元素,插入元素需要使用insert()方法。
6.2元素的删除
        删除操作采用erase()方法,可删除某个迭代器位置上的元素、等于某个键值的所有重复元素、一个迭代器区间上的元素。使用clear()方法可将multimap容器中的元素清空。
因为有重复的键值,所以,删除操作会将要删除的键值一次性从multimap中删除。
6.3元素的查找
        由于 multimap存在重复的键值,所以find()方法只返回重复键值中的第一个元素的迭代器位置,如果没有找到该键值,则返回end()迭代器位置。
 
 


7.deque 双端队列容器
    deque双端队列容器与 vector一样,采用线性表顺序存储结构。但与vector唯一不同的是,deque采用分块的线性存储结构来存储数据,每块的大小一般为512字节,
称为一个deque,所有的deque块使用一个 Map块进行管理,每个Map数据项记录各个 deque块的首地址。这样一来,deque块在头部和尾部都可插入和删除元素,
而不需移动其他元素(使用push_back()方法在尾部插入元素,会扩张队列;而使用push_front()方法在首部插入元素和使用insert()方法在中间插入元素,
只是将原位置上的元素值覆盖,不会增加新元素)。一般来说,当考虑到容器元素的内存分配策略和操作的性能时,deque相对于 vector更有优势。
7.1创建 deque对象
         创建 deque对象的方法通常有三种:
    (1)创建没有任何元素的deque对象:
    deque<int>d;
    (2)创建具有n 个元素的deque对象:
    deque<int>d(10);
    (3)创建具有n 个元素的deque对象,并赋初值:
    deque<int>d(10,8.5);
7.2插入元素
    (1)使用push_back()方法从尾部插入元素,会不断扩张队列。
    (2)从头部插入元素,不会增加新元素,只将原有的元素覆盖。
    (3)从中间插入元素,不会增加新元素,只将原有的元素覆盖。
7.3前向遍历
(1)以数组方式遍历。
for(i=0;i<d.size();i++)
{
cout<<d[i]<<"
";
}
(2)以前向迭代器的方式遍历。
deque<int>::iterator
it;
for(it=d.begin();it!=d.end();it++)
{
cout<<*it<<"
";
}
7.4反向遍历
采用反向迭代器对双端队列容器进行反向遍历。
deque<int>::reverse_iterator
rit;
for(rit=d.rbegin();rit!=d.rend();rit++)
{
cout<<*rit<<"
";
}
7.5删除元素
可以从双端队列容器的首部、尾部、中部删除元素,并可以清空双端队列容器。下面分别举例说明这 4种删除元素的操作方法。
(1)采用pop_front()方法从头部删除元素。
(2)采用pop_back()方法从尾部删除元素。
(3)使用erase()方法从中间删除元素,其参数是迭代器位置。//从中间删除元素,erase的参数是迭代器位置d.erase(it);
(4)使用clear()方法清空deque 对象。
 
 
 
 
8.list 双向链表容器
    list容器实现了双向链表的数据结构,数据元素是通过链表指针串连成逻辑意义上的线性表,这样,对链表的任一位置的元素进行插入、删除和查找都是极快速的。
list的每个节点有三个域:前驱元素指针域、数据域和后继元素指针域。前驱元素指针域保存了前驱元素的首地址;数据域则是本节点的数据;
后继元素指针域则保存了后继元素的首地址。list的头节点的前驱元素指针域保存的是链表中尾元素的首地址,list的尾节点的后继元素指针域则保存了头节点的首地址,
这样,就构成了一个双向循环链。由于 list对象的节点并不要求在一段连续的内存中,所以,对于迭代器,只能通过“++”或“--”的操作将迭代器移动到后继/前驱节点元素处。
而不能对迭代器进行+n-n的操作,这点,是与vector等不同的地方。
8.1创建 list对象
    (1)创建空链表:list<int>l;
    (2)创建具有n个元素的链表:list<int>l(10); //创建具有 10个元素的链表
8.2元素插入和遍历有三种方法往链表里插入新元素:
    (1)采用push_back()方法往尾部插入新元素,链表自动扩张。
    (2)采用push_front()方法往首部插入新元素,链表自动扩张。
    (3)采用insert()方法往迭代器位置处插入新元素,链表自动扩张。注意,迭代器只能进行“++”或“--”操作,不能进行+n-n的操作,因为元素的位置并不是物理相连的。
采用前向迭代器 iterator对链表进行遍历。
8.3反向遍历
         采用反向迭代器 reverse_iterator对链表进行反向遍历。
8.4元素删除
    (1)可以使用remove()方法删除链表中一个元素,值相同的元素都会被删除。
    (2)使用pop_front()方法删除链表首元素,使用pop_back()方法删除链表尾元素。
    (3)使用erase()方法删除迭代器位置上的元素。
    (4)使用clear()方法清空链表。
8.5元素查找
        采用find()查找算法可以在链表中查找元素,如果找到该元素,返回的是该元素的迭代器位置;如果没有找到,则返回end()迭代器位置。
    find()算法需要声明头文件包含语句“#include<algorithm>”
8.6元素排序
        采用 sort()方法可以对链表元素进行升序排列。
8.7剔除连续重复元素
        采用 unique()方法可以剔除连续重复元素,只保留一个。
 
 


9.bitset 位集合容器
bitset容器是一个 bit位元素的序列容器,每个元素只占一个bit ,取值为0 1,因而很节省内存空间。
bitset类提供的方法见下表。
        方法                                        功能
b.any()
                b 中是否存在置为 1的二进制位?
b.none()
                b 中不存在置为 1的二进制位吗?
b.count()
                 b 中置为 1的二进制位的个数
b.size()
                 b 中二进制位的个数
b[pos]
                 访问 b中在 pos处的二进制位
b.test(pos)
                 b 中在 pos处的二进制位是否为 1?
b.set()
                 b中所有二进制位都置为 1
b.set(pos)
                  b中在 pos处的二进制位置为 1
b.reset()
                  b中所有二进制位都置为 0
b.reset(pos)
                  b中在 pos处的二进制位置为 0
b.flip()
                  b中所有二进制位逐位取反
b.flip(pos)
                  b中在 pos处的二进制位取反
b.to_ulong()
                  b中同样的二进制位返回一个 unsignedlong 
os<< b            b中的位集输出到 os
 
9.1创建 bitset对象
        创建 bitset对象时,必须要指定容器的大小。bitset对象的大小一经定义,就不能修改了。
9.2设置元素值
    (1)采用下标法。
    (2)采用set()方法,一次性将元素设置为1
    (3)采用set(pos)方法,将某pos 位设置为1
    (4)采用reset(pos)方法,将某pos 位设置为0
9.3输出元素
    (1)采用下标法输出元素。
    (2)直接向输出流输出全部元素。
 


10.stack 堆栈容器
    stack堆栈是一个后进先出(LastIn First Out,LIFO)的线性表,插入和删除元素都只能在表的一端进行。插入元素的一端称为栈顶(StackTop),
而另一端则称为栈底(StackBottom)。插入元素叫入栈(Push),元素的删除则称为出栈(Pop)
堆栈的使用方法
堆栈只提供入栈、出栈、栈顶元素访问和判断是否为空等几种方法。
采用 push()方法将元素入栈;采用pop()方法出栈;采用top()方法访问栈顶元素;采用empty()方法判断堆栈是否为空,如果是空的,则返回逻辑真,否则返回逻辑假。
当然,可以采用size()方法返回当前堆栈中有几个元素。
 
 


11.queue 队列容器
    queue队列容器是一个先进先出(First In First Out,FIFO)的线性存储表,元素的插入只能在队尾,元素的删除只能在队首。
    queue队列的使用方法
    queue队列具有入队 push()(即插入元素)、出队pop()(即删除元素)、读取队首元素front()、读取队尾元素back()、判断队列是否为空empty()
队列当前元素的数目size()这几种方法。
 
 


12.priority_queue 优先队列容器
priority_queue优先队列容器与队列一样,只能从队尾插入元素,从队首删除元素。但它有一个特性,就是队列中最大的元素总是位于队首,所以出队时,
并非按先进先出的原则进行,而是将当前队列中最大的元素出队。这点类似于给队列里的元素进行了由大到小的顺序排序。元素的比较规则默认为按元素的值由大到小排序;
当然,可以重载“<”操作符来重新定义比较规则。
 
12.1优先队列的使用方法
        优先队列包含入队 push()(插入元素)、出队pop()(删除元素)、读取队首元素top()、判断队列是否为空empty()和读取队列元素数量size()等方法。
12.2重载“<”操作符来定义优先级如果优先队列的元素类型是结构体,可以通过在结构体中重载“<”操作符的方法来修改优先队列的优先性。
12.3重载“()”操作符来定义优先级如果优先队列的元素不是结构体类型,则可以通过重载“()”操作符的方式来定义优先级。
当然,元素是结构体类型,也可以通过重载“()”操作符的方式来定义优先级,而不是一定要在结构体内重载“<”操作符才行。

                
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值