顺序容器及其应用 (一)

来源:互联网 发布:手机拨号软件 编辑:程序博客网 时间:2024/06/05 23:53

前言

       一个容器就是一些特定类型对象的集合。顺序容器 提供了控制元素存储和访问顺序的能力。顺序是与之加入容器时的位置相对应的。

1.顺序容器概述

所有的顺序容器都提供了快速顺序访问元素的能力,但是,这些顺序容器在以下的方面都有不同的性能折中:

      vector         可变大小的数组。支持快速随机访问。在尾部之外插入或者删除元素可能很慢
      deque         双端队列,支持快速随机访问,在头尾位置插入或者删除速度很快
      list             双向链表,支持双向顺序访问,在list中的任何位置插入或者删除操作都很快。 
      forward_list    单向链表,只支持单向顺序访问,链表中的任何位置插入或者删除操作都很快 
      array              固定大小的数组,支持快速随机访问,不能添加或者删除元素。
     string   与vector相似的容器,但专门用于保存字符。随机访问快。在尾部插入删除速度快
     
    以上的容器中除了固定大小的array外,其他容器都提供了高效、灵活的内存管理。可以添加和删除元素的大小,扩张和收缩容器的大小。
stringvector将元素保存在连续的内存空间中,由于元素是连续存储的,由原素的下标来计算其地址是非常快速的,但是这两种容器中间位置添加或者删除元素就会非常的耗时,在一次添加或者删除后,需要移动删除或者插入元素之后的所有元素,来保持连续存储。而且,添加一个元素时,可能还需要分配额外的内存空间,在这种情况下,每个元素都必须移动到新的存储空间中。
list forward_list 两个容器的设计目的是令容器任何位置的添加,和删除操作都很快速。作为代价,这两容器不支持元素的随机访问。为了访问一个元素,只能遍历整个容器。而且,与vector、deque和array相比,这两个容器的额外开销也很大。
deque是一个更为复杂的数据结构。与string和vector类似,deque支持快速的随机访问。与string和vector一样,在deque的中间位置添加或者删除元素的代价(可能)很高。但是,在deque的两端添加或删除元素都是很快的,与list或forward_list添加删除元素的速度相当。

2.确定使用哪种顺序容器

通常,使用vector是最好的选择,除非你有很好的理由选择其他的容器。
下面是一下选择容器的基本原则:
1) 如果你的程序有很多的小的元素,且空间的额外开销很重要,则不要使用list或forward_list.
2) 如果程序要求随机访问元素,应使用vector或deque。
3) 如果程序要求在程序中删除或插入元素,应使用list或者forward_list.
4) 如果程序需要在头或者尾位置插入或者删除元素,但不会再中间位置插入或者删除元素操作,则使用deque。

3.容器的使用例子

先将数数组中的元素加入容器中,然后进行排序,并去掉重复的部分,最后进行输出。

#include <iostream>#include <vector>#include <algorithm>#include <iterator>using namespace std;int array[] = {2,2,1,2,3,4,4,6,6,7,7,6,5,4,8,8,9,9,9,2,3,4,2,2,2,7,11,14};int main(){vector<int> vec;int i;int len = sizeof(array)/sizeof(int);for(i = 0;i < len;++ i){vec.push_back(array[i]);  }sort(vec.begin(),vec.end()); // 对容器中的元素进行排序vector<int>::iterator iter;iter = unique(vec.begin(),vec.end());//找到重复的元素 vec.erase(iter,vec.end()); //删除重复的元素 for(i = 0;i < vec.size();++ i){cout << vec.at(i) << " ";  // 遍历打印容器中的元素}cout << endl;return 0;}

下面是vector 与 list的区别
#include<iostream>#include<vector>#include<list>using namespace std;int main(){    vector<int> vet;    list<int> lst;    for(int i=0;i<8;i++) ////往v和l中分别添加元素    {        vec.push_back(i);        lst.push_back(i);    }    cout << "vet[2]=" << vet[2] << endl;    //cout<< "lst[2]=" <<lst[2] << endl;  //编译错误,list没有重载[]的方法    cout<< (vec.begin()<vec.end()) <<endl;     //cout<< (lst.begin()<lst.end()) <<endl; /编译错误,list::iterator没有重载<或>    cout << *(vec.begin()+1) <<endl;    //cout << *(lst.begin()+1) << endl; //编译错误,list::iterator没有重载+    vector<int>::iterator itv = vec.begin();    list<int>::iterator itl = lst.begin();    itv = itv + 2;    //itl = itl + 2; //编译错误,list::iterator没有重载+    itv ++;        itl ++; //list::iterator中重载了++,只能使用++进行迭代访问。    cout << *itv << endl;    cout << *itl << endl;    return 0;}vector拥有一段连续的内存空间,能很好的支持随机存取,因此vector<int>::iterator支持“+”,“+=”,“<”等操作符。list的内存空间可以是不连续,它不支持随机访问,因此list<int>::iterator则不支持“+”、“+=”、“<”等vector<int>::iterator和list<int>::iterator都重载了“++”运算符。总之,如果需要高效的随机存取,而不在乎插入和删除的效率,使用vector;如果需要大量的插入和删除,而不关心随机存取,则应使用list。

4.容器对保存元素的限制

顺序容器基本上可以保存为任意的类型的元素。特别是,我们定义的一个容器,其元素的类型可以是另一个容器,这种容器的定义与任何其他的容器类型完全一样:在尖括号中指定元素类型(此种情况下,是另一种容器的类型):
vector<vector<string>> vect; // 容器的容器
此时,vect是一个vector,其元素类型是string的vector。






原创粉丝点击