您的位置:首页 > Web前端

《STL Tutorial Reference》 Chapt 6 Containers

2007-10-30 17:26 190 查看

Chapt 6 STL Containers

Content included:

How to use, internal data structures, operations, and the performance: general abilities, advantages, and disadvantages of all container types.

Sepecial classes: container adapters(: stack, queue, priority queue), bitmaps, and valarrays.

6.1 通用容器能力与操作

每个容器都具备的能力:

所有容器提供值而非引用语义。当插入时,容器内部拷贝元素而非管理它们的引用。因此,STL容器存储和的元素必须能拷贝,即需要public copy constructor
通常,所有的元素都有其次序。
通常,操作并非安全。调用者必须确保操作的参数满足要求。使用STL不会抛出异常。
通用操作:

初始化:每个容器类提供一个default constructor, copy constructor, destructor, 以及用另一个容器元素、数组、标准输入来初始化的constructor.
ConType c 
ConType c1(c2) 
ConType c(beg, end) 
c.~ConType() 
c.size() 
c.empty() 
c.max_size() 
c1 ==  c2 
c1 != c2 
c1 < c2 
c1 > c2 
c1 <= c2 
c1 >= c2 
c1 = c2assign operator
c1.swap(c2)member function
swap(c1, c2)global function
c.begin() 
c.end() 
c.rbeginreturn reverse iterator for 1st element
c.rend() 
c.insert(pos, elem) 
c.erase(beg, end)remove elements in range [beg, end)
c.clear()remove all
c.get_allocator() 
说下几种特殊的初始化方法:

数组初始化:

int array[] = {2, 3, 17} ..//std:set<int> c(array, array+sizeof(array)/sizeof(array[0]);


标准输入初始化:

std:deque<int> c((std::istream_iterator<int>(std::cin)), std::istream_iterator<int>());


6.2 Vector

模型:动态数组





 

提供随机访问。

容量:

capacity()  返回不重新分配内存的情况下最大可能的元素个数

max_size()  返回可以容纳的最大大小

这两个函数都是依赖于STL实现的

保留一定容量的以避免重新分配内存带来的耗时:

方式一:

std::vector<int> v;

v.reverve(80);  //reverve memory for 80 elements

方式二:

std::vector<int> v(5);

//creates a vector and initializes it with five values, call 5 times the default constructor of type T

推荐第一种方式

元素访问:

c.at(idx)return element in idx with range checking
c[idx]return element in idx with no range checking
c.front()return 1st element(no check 1st element exists)
c.back()return last element(no check last element exists)
c.at(idx)可以进行越界检查,超出范围会抛出错误异常。

 

下面代码:

std::vector<Elem> coll; //empty vector

coll[5] = elem;//RUNTIME ERROR? undefine behavior

std::cout << coll.front();RUNTIME ERROR? undefine behavior

迭代器函数:

c.begin()
c.end()
c.rbegin()
c.rend()
插入和删除元素:

c.insert(pos, elem) 
c.insert(pos, n, elem) 
c.insert(pos, beg, end) 
  
c.push_back(elem) 
c.pop_back() 
  
c.erase(pos) 
c.erase(beg,end) 
  
c.resize(num) 
c.resize(num, elem) 
  
c.clear() 
 

class vector<bool>

比通常是实现更节省空间,每个元素至少保留1bit

这样导致模板操作可能不适合vector<bool>

 

6.3 Deques

也是使用动态数组管理元素

 

deque典型的实现是用一束单个的block,第一block以一个方向增长,最后一个block以相反方向增长





和vector比较,操作只有2个不同:

deque没有提供capacity()和reverve()函数

deque提供了push_front()和pop_front()函数

6.4 List





插入和移除元素:

c.insert(pos, elem)
c.insert(pos, n, elem)
c.insert(pos, beg, end)
c.push_back(elem)
c.pop_back()
c.push_front(elem)
c.pop_back()
 
c.remove(val)
c.remove_if(op)
c.erase(pos)
c.erase(beg, end)
  
c.resize(num)
c.resize(num, elem)
 
c.clear()
但是,上述函数没有提供移除某个值的第一次出现

移接函数 (Splice Functions)

c.unique()移除重复元素
c.unique(op) 
c1.splice(pos,c2)c2的所有元素移到c1的pos前
c1.splice(pos, c2, c2beg, c2end)c2的[c2beg, c2end)范围内的元素移到c1的pos前
  
c.sort()按升序排序
c1.sort(op) 
  
c1.merge(c2)合并2个有序list c1和c2
c1.merge(c2, op) 
  
c.reverse()反转
  

6.5 Sets 和 Multisets

set通常实现为平衡二叉树(Balanced Binary Trees)

实际上,set和multiset典型的实现为红黑树(Red-black Trees)





自动排序的最大优点是搜索某个值时有很好的表现。

但是也有很大的限制,你不能直接改变元素的值,因为这可能会破坏正确的次序。因此要修改一个元素的值,你必须先移除拥有旧值的元素,然后插入一个拥有新值的元素。

set和multiset不提供直接元素访问的操作

通过iterator的间接访问有限制:从iterator的观点看,元素的值是constant

set<Type> cset<Type, op> c
set<Type> c(op)set<Type, op> c(op)
set<Type> c1(c2)set<Type, op> c1(c2)
set<Type> c(beg, end)set<Type, op> c(beg, end)
set<Type> c(beg, end, op)set<Type, op> c(beg, end, op)
c.~set<Type>()c.~set<Type, op>()
特殊的搜索操作:

count(elem) 
find(elem) 
lower_bound(elem)返回>=elem的位置
upper_bound(elem)返回>elem的位置
equal_range(elem) 
  
要理解lower_bound(elem), upper_bound(elem), equal_range(elem),看下面代码就清楚了:

#include <iostream>


[code]#include <set>


using namespace std;


int main ()


{


set<int> c;


c.insert(1);


c.insert(2);


c.insert(4);


c.insert(5);


c.insert(6);


cout << "lower_bound(3): " << *c.lower_bound(3) << endl;


cout << "upper_bound(3): " << *c.upper_bound(3) << endl;


cout << "equal_range(3): " << *c.equal_range(3).first << " "


<< *c.equal_range(3).second << endl;


cout << endl; cout << "lower_bound(5): " << *c.lower_bound(5) << endl;


cout << "upper_bound(5): " << *c.upper_bound(5) << endl;


cout << "equal_range(5): " << *c.equal_range(5).first << " "


<< *c.equal_range(5).second << endl; system("PAUSE");


return 0;


}

[/code]

插入和移除操作:

c.insert(elem) 
c.insert(pos, elem) 
c.insert(beg, end) 
c.erase(elem) 
c.erase(elem) 
c.erase(pos) 
c.erase(beg, end) 
c.clear() 
注意,insert函数的返回类型不同:

set

pair<iterator, bool> insert(const value_type &elem);

iterator             insert(iterator pos_hint, const value_type& elem);

multiset

iterator             insert(const value_type& elem);

iterator             insert(iteratir pos_hint, const value_type& elem);

set不提供remove()函数,而提供erase函数。

序列容器提供的erase()函数

iterator erase(iterator pos);

iterator erase(iterator beg, iterator end);

关联容器提供的erase()函数

void     erase(iterator pos)

void     erase(iterator beg, iterator end)

6.6 Map和Multimap





和set一样,通常map也是以平衡二叉树作为实现。

可以将set看作特殊的map:其key和value是相同的。

一点差别是:1)map的元素是key/value对 2)map可以作为关联数组

std::map<std::string,float> coll;     // empty collection

   /*insert "otto"/7.7 as key/value pair

    *-first it inserts "otto"/float()

    *-then it assigns 7.7

    */ 
coll["otto"] = 7.7;

 

总结:何时该使用何种容器?参考下表







默认情况下,你应该使用vector.它有最简单的内部数据结构并提供了随机访问。这样,数据访问是方便且灵活,并且数据处理也是足够快

如果你经常在序列开始和结尾插入/删除元素,你应该使用deque.另外,如果这是重要的:当元素移除时,由容器使用的内部存储量减少时,你也应使用deque。再者,因为vector通常使用一个block,而deque可能包含更多的元素,因为它使用多个block

如果你插入、移除或移动元素经常发生在容器中间,考虑使用list。list提供特殊的成员函数以常数时间来从一个容器移动元素到另一个。但是注意,因为List没有提供随机访问,当你只拥有list的起始,在访问元素时你可能遇到困难

像所有的node-based容器,list没有使指向元素的iterator无效,只要这些元素是容器的一部分。vector使得所有超出容量的iterator、指针、引用无效。deque当改变它们的size,也使相应的iterator、指针、引用无效。

如果你需要一个能handle exception的容器:每个操作或者成功或者无效,你应使用list或者关联容器。

如果你通常需要依据搜索准则搜索元素,使用set或multiset.

在搜索1000个元素时,O(Logn)理论上比O(n)快10倍,hash表通常比二叉树快5~10倍。如果hash容器可取得,你可以考虑使用

如果为了处理key/value对,使用map或multimap(或hash)

如果你需要一个字典,使用multimap

6.10 容器类内部定义细节:

6.10.1 Type Definitions

container::value_type

元素类型

vector:  typedef _Tp   value_type;

set/multiset:(记住这个value_type是const)

typedef _Key     key_type;

typedef _Key     value_type;

map/multimap:

typedef     _Key           key_type;

typedef     _Tp            mapped_type;

typedef     pair<const _Key,_Tp>   value_type;

vector,deque,list,set/multiset,map/multimap,string提供

container::reference

容器元素的引用

典型情况下为: container::value_type&

vector,deque,list,set/multiset,map/multimap,string提供

container::const_reference

容器const元素的引用

典型情况下为: cosnt container::value_type&

vector,deque,list,set/multiset,map/multimap,string提供

container::iterator

iterator类型

vector,deque,list,set/multiset,map/multimap,string提供

container::const_iterator 

constant iterators类型. 

vector,deque,list,set/multiset,map/multimap,string提供

container::reverse_iterator 

reverse iterators类型. 

vector,deque,list,set/multiset,map/multimap提供

container::const_reverse_iterator 

constant reverse iterators类型. 

vector,deque,list,set/multiset,map/multimap,string提供

container::size_type 

unsigned int类型 for size values. 

vector,deque,list,set/multiset,map/multimap,string提供

container::difference_type 

signed int类型 for difference values.

vector,deque,list,set/multiset,map/multimap,string提供

container::key_type

For sets and multisets, it is equivalent to value_type. 

set/multisets, map/multimap提供.

container::mapped_type 

The type of the value of the elements of associative containers. 

map/multimap提供.

container::key_compare 

The type of the comparison criterion of associative containers. 

set/multiset, map/multimap提供.

container::value_compare 

The type of the comparison criterion for the whole element type.  For sets and multisets, it is equivalent to key_compare.  For maps and multimaps, it is an auxiliary class for a comparison criterion that compares

only the key part of two elements.  Provided by sets, multisets, maps, and multimaps.

container::allocator_type 
The type of the allocator. 

vector,deque,list,set/multiset,map/multimap,string提供

6.10.2 Construct, Copy, Destruct 操作

container::container()

explicit container::container(const CompFunc& op)

explicit container::container(const container& c)

explicit container::container(size_type num)

container::container(size_type num, const T& value)

container::container(InputIterator beg, InputIterator end)

container::container(InputIterator beg, InputIterator end, const ComFunc& op)

container::~container()

6.10.3 非修改操作

size操作

size_type container::size() const

bool container::empty() const

size_type container::max_size() const

以上vector,deque,list,set/multiset,map/multimap,string都提供

capacity操作

container::capacity() const

vector,string提供

container::reserve() const

vector,sting提供

比较操作

bool operator ==(const container& c1, const container& c2)

bool operator !=(const container& c1, const container& c2)

bool operator > (const container& c1, const container& c2)

bool operator < (const container& c1, const container& c2)

bool operator >=(const container& c1, const container& c2)

bool operator <=(const container& c1, const container& c2)

两个容器有相同数目的元素,并且按次序相等,返回true

关联容器的特殊非修改操作

size_type container::count(const T& value) const

线性复杂度

iterator container::find(const T& value)

const_iterator container::find(const T& value) const

find()算法的特殊版本

log复杂度

iterator container::lower_bound(const T& value)

const_iterator container::lower_bound(const T& value)

iterator container::upper_bound(const T& value)

const_iterator container::upper_bound(const T& value)

log复杂度

pair<iterator, iterator>container::equal_range(const T& value)

pair<const_iterator, const_iterator>container::equal_range(const T& value) const

6.10.4 assignment操作

container& container::operator=(const container& c)

void container::assign(size_type num, const T& value)

将容器所有元素清空,并指派num个元素,值都为value

void container::assign(InputIterator beg, InputIterator end)

以上两个assign函数只有vector,deque,list,string提供

void container::swap(container& c)

void swap(container& c1, container& c2)

6.10.5 直接访问操作

reference container::at(size_type idx)

const_reference container::at(size_type idx) const

reference container::operator [](size_type idx)

const_reference container::operator [](size_type idx) const

T& map::operator[](const key_type& key)

此即关联数组,只有map提供

reference container::front()

const_reference container::front()

vector, deque, list提供

reference container::back()

const_reference container::back()

vector, deque, list提供

6.10.6 生成iterator的操作



 

iterator container::begin()

const_iterator container:: begin () const 

iterator container::end()

const_iterator container::end() const 

reverse_iterator container::rbegin()

const_reverse_iterator container::rbegin() const 

reverse_iterator container::rend()

const_reverse_iterator container::rend() const

以上所有容器都提供

6.10.7 Insert / Remove 操作

insert:

iterator container::insert(const T& value)

set, map提供

pair<iterator,bool> container::insert(const T& value)

multiset, multimap提供

iterator container::insert(iterator pos, const T& value)

所有容器都提供

void container::insert(iterator pos, size_type num, const T& value)

仅顺序容器提供

void container::insert(InputIterator beg, InputIterator end)

仅关联容器提供

void container::insert(iterator pos, InputIterator beg, InputIterator end)

仅顺序容器提供

void container::push_front(const T& value)

void container::pop_front()

仅deque,list提供

void container::push_back(const T& value)

void container::pop_back()

vector, deque, list,string提供

remove:

void list::remove(const T& value)

void list::remove_if(UnaryPredicate op)

仅list提供

删除所有list中值等于value的元素

顺序容器中唯一提供以值的方式删除的容器,其他顺序容器要以值方式删除,必须使用find()算法得到iterator

 

erase:

 size_type container::erase (const T& value)

关联容器提供

void container::erase(iterator pos)

void container::erase(iterator beg, iterator end)

关联容器提供

iterator container::erase(iterator pos)

iterator container::erase(iterator beg, iterator end)

顺序容器提供

resize:

void container::resize(size_type num)

void container::resize(size_type num, T value)

顺序容器提供..这个比较特别,可能引起iterator无效

clear:

void container::clear()

所有容器都提供

6.10.8 List的特殊成员函数

 

void list::unique()

void list::unique(BinaryPredicate op)

void list::splice(iterator pos, list& source)

void list::splice(iterator pos, list& source, iterator sourcePos)

void list::splice(iterator pos, list& source, iterator sourceBeg, iterator sourceEnd)

void list::sort()

void list::sort(CompFunc op)

void list::merge(list& source)

void list::merge(list& source, CompFunc op)

标准要求两list是已排序的,但是你也可以使用2未排序的list

未测试过有何区别(((!!!

void list::reverse ()

6.10.9 Allocator支持


待续..



6.11.9 Exception handle

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: