c++ STL总结一:vertor和list

STL提供六大组件,彼此可以组合套用

1、容器(containers):各种数据结构,如vertor,list,deque,set,map.从实现的角度来看,STL容器是一种class template

2、算法(algorithms):各种算法如sort,search,copy,earse。STL算法是一种 function template。

3、迭代器(iterators):扮演容器与算法之间的胶合剂,是所谓的“泛型指针”。所有STL容器都有自己的专属的迭代器。

4、仿函数(functors):行为类似函数,可以作为算法的某些策略。从实现的角度来看,仿函数是一种重载了operator()的class或class template。

5、配接器(adapters):一种用来修饰容器或仿函数或迭代器借口的东西。例如queue和stack

6、配置器(allocators):负责空间的配置与管理。配置器是一个实现了动态空间分配、空间管理、空间释放的class template。

STL是建立在泛化之上的。数组泛化为容器,参数化了所包含的对象的类型。函数泛化为算法,参数化了所用的迭代器的类型。指针泛化为迭代器,参数化了所指向的对象的类型。

vector、string、deque和list被称为标准序列容器,

set、multiset、map和multimap是标准关联容器。

非标准序列容器slist和rope。slist是一个单向链表,rope本质上是一个重型字符串。

非标准关联容器hash_set、hash_multiset、hash_map和hash_multimap。

标准非STL容器,包括数组、bitset、valarray、stack、queue和priority_queue。

迭代器被分成五个种类:

输入迭代器是每个迭代位置只能被读一次的只读迭代器。

输出迭代器是每个迭代位置只能被写一次的只写迭代器。

输入和输出迭代器被塑造为读和写输入和输出流(例如,文件)。

前向迭代器有输入和输出迭代器的能力,但是它们可以反复读或写一个位置。

双向迭代器就像前向迭代器,除了它们的后退可以像前进一样容易。标准关联容器都提供双向迭代器。list也有。

连续内存容器(也叫做基于数组的容器)在一个或多个(动态分配)的内存块中保存它们的元素。如果一个新元素被查入或者已存元素被删除,其他在同一个内存块的元素就必须向上或者向下移动来为新元素提供空间或者填充原来被删除的元素所占的空间。这种移动影响了效率和异常安全。标准的连续内存容器是vector、string和deque。非标准的rope也是连续内存容器。

基于节点的容器在每个内存块(动态分配)中只保存一个元素。容器元素的插入或删除只影响指向节点的指针,而不是节点自己的内容。所以当有东西插入或删除时,元素值不需要移动。表现为链表的容器——比如list和slist——是基于节点的,所有的标准关联容器也是(它们的典型实现是平衡树)。非标准的散列容器使用不同的基于节点的实现。

1、vector

vector和数组类似,它拥有一段连续的内存空间,并且起始地址不变,因此它能非常好的支持随机存取(即使用[]操作符访问其中的元素),但由于它的内存空间是连续的,所以在中间进行插入和删除会造成内存块的拷贝(复杂度是O(n)),另外,当该数组后的内存空间不够时,需要重新申请一块足够大的内存并进行内存的拷贝。这些都大大影响了vector的效率。

vector不是一种数据类型,而只是一个类模板,可用来定义任意多种数据类型。vector类型的每一种都指定了其保存元素的类型。因此,vector<int>和vector <string>都是数据类型。

vector对象的定义和初始化


vector<T>  v1;


vector保存类型为T的对象。默认构造函数v1为空。


vector<T> v2(v1);


v2是v1的一个副本。


vector<T> v3(n, i);


v3包含n个值为i的元素。

vector<int> ivec4(10, -1);     // 10 elements, each initialized to -1

vector<string> svec(10, "hi!"); // 10 strings, each initialized to "hi!"

vector的操作


v.empty()


如果v为空,则返回true,否则返回false。


v.size()


返回v中元素的个数。


v.push_back(t)


在v的末尾增加一个值为t的元素。


v[n]


返回v中位置为n的元素。


v1 = v2


把v1的元素替换为v2中元素的副本。


v1 == v2


如果v1与v2相等,则返回true。


!=, <, <=, >, >=


保持这些操作符惯有的含义。

vector添加元素:

string word;

vector<string> text;        // empty vector

while (cin >> word) {

    text.push_back(word);  // append word to text

}

  vector的下标操作:

for (vector<int>::size_type ix = 0; ix != ivec.size(); ++ix)

    ivec[ix] = 0;

  

 vector迭代器

 每种容器都定义了一对命名为begin和end的函数,用于返回迭代器。如果容器中有元素的话,由begin返回的迭代器指向第一个元素:

vector<int>::iterator iter = ivec.begin();

  由end操作返回的迭代器指向vector的“末端元素的下一个”。通常称为超出末端迭代器(off-the-end iterator),表明它指向了一个不存在的元素。如果vector为空,begin返回的迭代器与end返回的迭代器相同。

for (vector<int>::iterator iter = ivec.begin(); iter != ivec.end(); ++iter)

    *iter = 0;  // set element to which iter refers to 0

  const_iterator

前面的程序用vector::iterator改变vector中的元素值。每种容器类型还定义了一种名为const_iterator的类型,该类型只能访问容器内元素,但不能改变其值。

for (vector<string>::const_iterator iter = text.begin();  iter != text.end(); ++ iter)

    *iter = " ";     // error: *iter is const

  

 

2、list

list是由数据结构中的双向链表实现的,因此它的内存空间可以是不连续的。因此只能通过指针来进行数据的访问,这个特点使得它的随机存取变的非常没有效率,需要遍历中间的元素,搜索复杂度O(n),因此它没有提供[]操作符的重载。但由于链表的特点,它可以以很好的效率支持任意地方的删除和插入。

list::iterator与vector::iterator的一些不同:

#include <iostream>

#include <vector>

#include <list>

using namespace std;

int main( void )

{

        vector<int> v;

        list<int> l;

        

        for (int i=0; i<8; i++)     //往v和l中分别添加元素

        {

                v.push_back(i);

                l.push_back(i);

        }

        

        cout << "v[2] = " << v[2] << endl;

        //cout << "l[2] = " << l[2] << endl;       //编译错误,list没有重载[]

        cout << (v.begin() < v.end()) << endl;

        //cout << (l.begin() < l.end()) << endl;   //编译错误,list::iterator没有重载<或>

        cout << *(v.begin() + 1) << endl;

        

        vector<int>::iterator itv = v.begin();

        list<int>::iterator itl = l.begin();

        itv = itv + 2;

        //itl = itl + 2;                  //编译错误,list::iterator没有重载+

        itl++;itl++;                    //list::iterator中重载了++,只能使用++进行迭代访问。

        cout << *itv << endl;

        cout << *itl << endl;

        return 0;

}

由于vector拥有一段连续的内存空间,能非常好的支持随机存取,因此vector<int>::iterator支持“+”、“+=”、“<”等操作符。
而list的内存空间可以是不连续,它不支持随机访问,因此list<int>::iterator则不支持“+”、“+=”、“<”等操作符运算,因此代码20、26行会有编译错误。只能使用“++”进行迭代,例如代码27行,使用两次itl++来移动itl。还有list也不支持[]运算符,因此代码18行出现编译错误。
总之,如果需要高效的随即存取,而不在乎插入和删除的效率,使用vector;如果需要大量的插入和删除,而不关心随即存取,则应使用list。

vector拥有一段连续的内存空间,因此支持随机存取,如果需要高效的随即存取,而不在乎插入和删除的效率,使用vector。
list拥有一段不连续的内存空间,因此支持随机存取,如果需要大量的插入和删除,而不关心随即存取,则应使用list。当大部分插入和删除发生在序列的头或尾时可以选择deque这种数据结构。

时间: 2025-01-07 04:22:37

c++ STL总结一:vertor和list的相关文章

STL Vector容器

STL Vector容器 Vector容器简介 vector是将元素置于一个动态数组中加以管理的容器.        vector可以随机存取元素(支持索引值直接存取, 用[]操作符或at()方法,这个等下会详讲).         vector尾部添加或移除元素非常快速.但是在中部或头部插入元素或移除元素比较费时        头文件:#include<vector> vector对象的默认构造 vector采用模板类实现, vector对象的默认构造形式: vector<T>

c++复习:STL之容器

1 STL的string 1 String概念 string是STL的字符串类型,通常用来表示字符串.而在使用string之前,字符串通常是用char*表示的.string与char*都可以用来表示字符串,那么二者有什么区别呢. string和char*的比较 string是一个类, char*是一个指向字符的指针. string封装了char*,管理这个字符串,是一个char*型的容器. string不用考虑内存释放和越界. string管理char*所分配的内存.每一次string的复制,取

STL学习思想

1.模版:一定要注意参数和返回值的模版 2.STL一系列的API:一定要注意返回值 3.容器中的都是值拷贝,而不是引用,在执行插入时,内部实行拷贝动作,所以STL中插入类时,一般都必须:无参构造函数,拷贝构造函数,重载=运算符,必须的自己重写,达到深拷贝!!! 4.一元谓词:函数只有一个参数,谓词:代表函数的返回值必须为bool类型;   二元谓词:函数只有二个参数,谓词:代表函数的返回值必须为bool类型; 5.算法和具体的数据类型相分离:通过函数对象(仿函数)来实现,本质:函数指针!!! 6

C++ STL学习——vector

学过C++的人肯定会很熟悉STL标准模板库,STL其实就是封装了一系列的接口,供我们调用.很多函数或者算法的实现不需要我们从头开始写,大大提高我们的编程效率.这篇博客在简单介绍STL的情况下,会详细的来介绍vector的使用. STL共有六大组件: 一.容器(Container):是一种数据结构,如list,vector,deque,queue等,以模板类的方法提供,为了访问容器中的数据,可以使用由容器类提供的迭代器. 二.迭代器(Iterator):提供了访问容器中对象的方法. 三.算法(Al

C++ STL中Map的按Key排序和按Value排序

原文  http://blog.csdn.net/iicy266/article/details/11906189 map是用来存放<key, value>键值对的数据结构,可以很方便快速的根据key查到相应的value.假如存储学生和其成绩(假定不存在重名,当然可以对重名加以区分),我们用map来进行存储就是个不错的选择. 我们这样定义,map<string, int>,其中学生姓名用string类型,作为Key:该学生的成绩用int类型,作为value.这样一来,我们可以根据学

stl容器区别: vector list deque set map及底层实现

在STL中基本容器有: vector.list.deque.set.map set 和map都是无序的保存元素,只能通过它提供的接口对里面的元素进行访问 set :集合, 用来判断某一个元素是不是在一个组里面,使用的比较少 map :映射,相当于字典 ,把一个值映射成另一个值,如果想创建字典的话使用它好了 底层采用的是树型结构,多数使用平衡二叉树实现 ,查找某一值是常数时间,遍历起来效果也不错, 只是每次插入值的时候,会重新构成底层的平衡二叉树,效率有一定影响. vector.list.dequ

STL vector,deque,list

一.vector可变长的动态数组必须包含头文件 #include <vector>支持随机访问迭代器• 根据下标随机访问某个元素时间为常数• 在尾部添加速度很快• 在中间插入慢所有STL算法 都能对vector操作 构造函数初始化:vector();无参构造函数, 将容器初始化成空的vector(int n);将容器初始化成有n个元素vector(int n, const T & val);假定元素类型是T, 将容器初始化成有n个元素, 每个元素的值都是valvector(iterat

C++ STL hash_map的使用以及STL hash_map的大“坑”

计算机编程中经常会用到hash表,而在C++中,使用STL编程更是少不了的.本文将介绍STL中hash_map的使用.在hash_map中使用自定义类型作为key值的方法以及在使用char *类型作为key值时遇到的问题. 一.需要的头文件以及命名空间 在linux下使用STL hash_map除了需要引用其所在头文件<hash_map>之外还要引用其命名空间.像这样写  1 using namespace __gnu_cxx; 二.hash_map的定义 先来看看hash_map是怎么定义的

c++ STL容器初探

什么是容器 首先,我们必须理解一下什么是容器,在C++ 中容器被定义为:在数据存储上,有一种对象类型,它可以持有其它对象或指向其它对像的指针,这种对象类型就叫做容器.很简单,容器就是保存其它对象的对象,当然这是一个朴素的理解,这种"对象"还包含了一系列处理"其它对象"的方法,因为这些方法在程序的设计上会经常被用到,所以容器也体现了一个好处,就是"容器类是一种对特定代码重用问题的良好的解决方案". 容器还有另一个特点是容器可以自行扩展.在解决问题时