C++学习 8 深入 STL 2

来源:互联网 发布:华科何琨 知乎 编辑:程序博客网 时间:2024/06/05 02:46
  • 深入Deque, queue, stack
  • RB_tree
  • set/multiset
  • hashtable
  • 补充unordered 容器

深入Deque, queue, stack

Deque 双端队列有iterator, 可以insert deque的模板声明: template < class T, class Allocator = allocator< T> > class deque;由 分段的连续空间构成 。deque 维护两个deque iterator start 和finish。一个map_pointer 类型为T** 指向map开始,一个size_type map_size.一个deque_iterator 又维护4个指针3个T* cur,first,last 分别指向当前buffer的current,first,last位置,一个map_pointer (T** 类型)指向map中此buffer存储位置。iterator start的first 指向第一个buffer的开始位置,finish的 last指向最后一个buffer的最后位置。可以向前向后push_front, push_back 元素 ,也可以insert元素。
iterator inert(iterator position, const value_type& x) { if (position.cur == start.cur)
{ push_front(x);//如果安插点在开始处则直接
push_front return start;
} else if (position.cur == finish.cur)
{ push_back(x); iterator tmp = finish; --tmp;//push_back 后finish会更新所以要--
return tmp;
} else
return insert_aux(position, x);
}
template <class T, class Alloc, size_t Bufsize> typename deque<T, Alloc,BufSize>::iterator deque<T,Alloc,BufSize>::insert_aux(iterator pos, const value_type& x)
{ difference_type index = pos - start;//安插点之前的元素个数 value_type x_copy = x;
if(index < size()/2) { push_front(front());
...
copy(front2, pos1, front1);
//如果在前半部分安插则在最前面push一个第一个元素,在将其后面到pos位置的元素向前copy移动一格。
} else { push_back(back());
... copy(pos, back2, back1) }
*pos = x_copy;
return pos;
}

deque 利用iterator 来模拟连续空间
Self operator + (differece_type n) { self tmp = *this; return tmp += n;
}
reference operator[] (size_type n) { return *(*this + n)]; } refernce operator*() const {return *cur;} pointer operator-> const { return &(operator*()); }
differnce_type operator - (const self& x) const { return difference_type(buffer_sie()) * (node - x.node -1) + (cur - first) + (x.last -x.cur); }
void set_node(map_pointer new_node) { node = new_node; first = *new_node; last = first + difference_type(buffer_size()); } self& operator += (differnce_type n) {
differece_type offset = n+ (cur - first);
if (offset >= 0&& offset < differnce_type(buffer_size()))//位于同一缓冲区
cur += n;
} else {
difference_type node_offset = offset > 0? offset/ difference_type(buffer_size()): -differnce_type(-offset - 1)/buffer_size();
set_node(node + node_offset);
cur = first + offset - node_offset* difference_type(buffer_size());
}
queue 是先进先出队列只能push,pop 故不提供iterator stack是先进后出队列也不提供iterator, 这两个adptor 都不允许遍历。vector不提供pop_front方法故不可以作为queue的底层容器。同理set和map均不可做stack,queue的底层容器。 ## rb_tree红黑树 ## 是一种平衡二元搜索树,提供遍历操作正常++ite便能获得排序状态。不应该使用iterator来改变元素的值,否则会破坏其排序状态。提供两种insert 操作: inert_unique(),insert_equal() 前者表示key独一无二否则安插失败,后者表示key可重复。
template <class Key,class value,class KeyOfValue, class compare,class Alloc = alloc > class rb_tree {
protectd:
typedef __rb_tree_node <Value> rb_tree_node; ... public: typedef rv_tree_node* link_type;
...
protected: size_type node_count; link_type header; compare key_compare;
... };

set 和multiset均以rb_tree 为底层结构区别是set使用inset_unique multiset() 使用insert_equal().
template <class Key,class Compare = less<Key>, class Alloc = alloc> class set {
public:
typedef Key key_type;
typedef Key value_type;
typedef Compare Key_compare;
typedef Compare value_compare;
private: typedef rb_tree<key_type, value_type, identity<value_type>, key_compare, Alooc> rep_type;
public: typedef typename rep_type::const_iterator iterator; ... };
template <class Arg, class Result> struct unary_function { typedef Arg argument_type; typedef Result result_type; };
template<class T> struct identity: public unary_function <T, T> { const T& operator()(const T& x) const {return x;} };

同理map/multimap 也是以rbtree 为底层结构, 不同是’value_type’ 为pair< const Key, T>. key 不能改变但是value 可以。

hashtable

hash table的实现有线性探测、二次探测、二次散列等实现,SGI的STL是采用开链法(separate chaining)来实现的。大概原理就是在hash table的每一项都是个指针(指向一个链表),叫做bucket。这样的话如果多个key值散列到同一位置,那么就存储到这个位置对应的链表中。如下图所示:这里写图片描述

0 0
原创粉丝点击