顺序容器及其应用 (一)

前言

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

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。






评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值