《STL Tutorial Reference》 Chapt 6 Containers

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 通用容器能力与操作

每个容器都具备的能力:

  1. 所有容器提供值而非引用语义。当插入时,容器内部拷贝元素而非管理它们的引用。因此,STL容器存储和的元素必须能拷贝,即需要public copy constructor
  2. 通常,所有的元素都有其次序。
  3. 通常,操作并非安全。调用者必须确保操作的参数满足要求。使用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 = c2 assign operator
    c1.swap(c2) member function
    swap(c1, c2) global function
    c.begin()  
    c.end()  
    c.rbegin return 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

模型:动态数组

image

 

提供随机访问。

容量:

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以相反方向增长

image

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

  1. deque没有提供capacity()和reverve()函数
  2. deque提供了push_front()和pop_front()函数

6.4 List

stl_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)

stl_set_internal

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

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

  • set和multiset不提供直接元素访问的操作
  • 通过iterator的间接访问有限制:从iterator的观点看,元素的值是constant
set<Type> c set<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> 
#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; 
}

插入和移除操作:

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

stl_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;

 

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

container_comp1container_comp2

  • 默认情况下,你应该使用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_cata 

  • 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

posted @ 2007-10-30 17:26  中土  阅读(1401)  评论(0编辑  收藏  举报
©2005-2008 Suprasoft Inc., All right reserved.