<stl>序列式容器

所谓序列容器即容器其中的元素都可序,但未必有序。常见的序列容器包括vector,list,deque,queue以及stack.

stl-4-1

  1. vector

array是静态空间,一旦配置就不可改变。vector是动态空间,随着元素的加入,内部机制会自动扩充以容纳新元素。

stl-4-2

1.1迭代器

vector维护的是一个线性区间,所以无论元素类型为何,普通指针都可以作为vector的迭代器而满足所有的必要条件。vector支持随机存取,而普通指针正好具备这样的能力,所以vector提供的是随机读取迭代器。即Random Access Iterators.

template <class T,class Alloc = alloc>
class vector{
public:
    typedef T               value_type;
    typedef value_type*     iterator;   //vector的迭代器时普通指针
...
};

1.2 分配器

vector缺省使用alloc作为空间分配器,并据此另外定义了一个data_allocator.为的是更方便的以元素大小为配置单位。

template<class T,class Alloc = alloc>
class vector{
protected:
    typedef simple_alloc<value_type,Alloc> data_allocator;
...
};

因此,data_allocator::allocate(n)表示分配n个元素空间。

1.3常见操作:

Vector_se<int> ve(10,10,4);
    //size()测试
    int size = ve.size();
    cout << "size: "<<size << endl;
    //insert()函数测试
    ve.insert(11);
    ve.insert(4,19);
    ve.insert(5,78);
    for(int i = 0 ; i < ve.size(); i++){
        cout << ve[i] << endl;
    }
    cout << ve.empty() << endl;
    int flag_disorder = ve.disordered();
    //输出逆序对数
    cout << flag_disorder << endl;
    //stl中的vector
    int i;
    vector<int> v(2,9);
    cout <<"size:" << v.size() << endl;
    cout << "capacity:" << v.capacity() << endl;
    v.push_back(1);
    cout <<"size:" << v.size() << endl;
    cout << "capacity:" << v.capacity() << endl;
    v.push_back(3);
    cout <<"size:" << v.size() << endl;
    cout << "capacity:" << v.capacity() << endl;
    v.push_back(4);
    cout <<"size:" << v.size() << endl;
    cout << "capacity:" << v.capacity() << endl;
    vector<int>::iterator iter = find(v.begin(),v.end(),3);
    if(iter != v.end()){
        cout << "finded" << endl;
        v.erase(iter);
    }
    v.insert(iter,5);
    for(int i = 0 ; i < v.size(); i++){
        cout << v[i] << endl;
    }
    v.clear();
插入操作导致容器容量增加,此时会发生扩容操作,即会造成原先的迭代器失效。
2、list
2.1 节点
template <class T>
struct __list_node{
    typedef void* void_pointer;
    void_pointer prev;  //类型为void*
    void_pointer next;
    T data;
};
 stl-4-3 

2.2 迭代器

list不像vector一样,以普通指针作为迭代器,因为其节点在空间中不保证连续存在。list迭代器必须保证指向list的节点,并能够递增,递减,取值以及成员存取等操作。list中是双向链表。所以迭代器必须具备前移和后移的能力。list的插入和接合操作都不会造成原有的list迭代器失效,对于删除操作,也只有”指向被删除元素“的那个迭代器失效,其它迭代器不受任何影响。

SGI list不仅是一个双向链表,还是一个环状双向链表。所以它只需要一个指针,便可完整表现整个链表。

template <class T, class Alloc = alloc>
class list {
protected:
    typedef __list_node<T> list_node;
public:
    typedef list_node* link_type;

protected:
    link_type node; //只要一个指针,便可表示整个环状双向链表
};

iterator begin() { return (link_type)((*node).next); }
iterator end() { return node; }
size_type size() const {
    size_type result = 0;
    distance(begin(), end(), result);
    return result;
}

stl-4-5

2.3 分配器

list缺省使用alloc作为空间分配器,并据此另外定义了一个list_node_allocator,为的是更方便以节点大小为配置单位:

template <class T, class Alloc = alloc>
class list {
protected:
    typedef simple_alloc<list_node, Alloc> list_node_allocator;
...
};

因此,list_node_allocator::allocate(n)表示分配n个节点空间

2.4 list常见操作

  • 节点操作
    • 分配节点:get_node()
    • 释放节点:put_node()
    • 生成一个节点:create_node()
    • 销毁一个节点:destory_node()
    • 节点插入:push_back(),push_front(),insert()
    • 节点移除:erase(),pop_back()和pop_front()
    • 移除某一数值的所有节点:remove()
    • 移除相同节点值的连续节点:unique()
  • 链表操作
    • 创建空链表:list(),empty_initialize()
    • 链表清空:clear()
  • 链表拼接:splice()
    • 将[first,last)内的元素移动到position之前,transfer(first,last)区间可以在同一个list内,也可以是两个不同的list.

stl-4-6

3.deque

deque是一种双向开口的连续线性空间。

deque和vector最大的差异:

  • deque允许常数时间内对起头端进行元素的插入或者移除操作。
  • deque没有所谓容量观念,因为它是动态地以分段连续空间组合而成,随时可以增加一段新的空间并链接起来(deque没有必要提供所谓的空间保留功能)

3.1 迭代器

deque是分段连续空间。维持其”整体连续“假象的任务,落在了迭代器的operator++和operator--两个运算子身上。deque迭代器必须能够指出分段连续空间(即缓冲区)在哪;必须能够判断自己是否已经处于其所在缓冲器的边缘。为了能够正确跳跃,迭代器必须随时掌握中控器map。

3.2deque的数据结构

deque采用一块所谓的map作为主控(中控器)。这里所谓的map是指一小块连续空间,其中每个元素都是一个指针,指向另一段(较大的)连续线性空间,称为缓冲区。缓冲区才是deque的存储空间主体。SGI STL允许我们指定缓冲区大小,默认值0表示使用512bytes缓冲区。

stl-4-7

deque的中控器,缓冲区,迭代器的关系如下

stl-4-8

3.4常见操作

  • deque的构造和初始化:deque()
  • 插入:push_back(),push_front(),insert().
  • 弹出:pop_back(),pop_front()
  • 清除所有:clear()
  • 清除某个空间:erase()

4.stack

具有”修改某物接口,形成另一种风貌“的性质者,称为适配器。因此,STL stack往往不被归类为容器,而被归类为容器适配器.stack不能被遍历,因而没有迭代器

template <class T, class Sequence = deque<T> >
class stack {
  //以下__STL_NULL_TMPL_ARGS会展开为 <>
  friend bool operator== __STL_NULL_TMPL_ARGS (const stack&, const stack&);
  friend bool operator< __STL_NULL_TMPL_ARGS (const stack&, const stack&);
public:
  typedef typename Sequence::value_type value_type;
  typedef typename Sequence::size_type size_type;
  typedef typename Sequence::reference reference;
  typedef typename Sequence::const_reference const_reference;
protected:
  Sequence c;   //底层容器
public:
  //以下完全利用Sequence c的操作,完成stack的操作
  bool empty() const { return c.empty(); }
  size_type size() const { return c.size(); }
  reference top() { return c.back(); }
  const_reference top() const { return c.back(); }
  //deque是两头可进出,stack是后进后出
  void push(const value_type& x) { c.push_back(x); }
  void pop() { c.pop_back(); }
};

template <class T, class Sequence>
bool operator==(const stack<T, Sequence>& x, const stack<T, Sequence>& y) {
  return x.c == y.c;
}

template <class T, class Sequence>
bool operator<(const stack<T, Sequence>& x, const stack<T, Sequence>& y) {
  return x.c < y.c;
}

只有stack顶端的元素有机会被外界取用,stack不提供遍历功能,也不提供迭代器。可以指定其它容器作为stack的底部容器。

5.queue:队列,是一种先进先出的数据结构,尾端插入,首部移出。只有首部元素才有机会被外界取用,queue不提供遍历功能,也不提供迭代器。指定其它容器作为queue的底层容器的方法:

queue<int,list<int> > iqueue;

6、heap

heap并不归属与STL容器组件,它是个幕后英雄,扮演priority queue的助手.heap是一颗完全二叉树,完全二叉树使用数组实现,因此使用一个vector作为heap的结构,然后通过一组xxx_heap算法,使其符合heap的性质.

  • push_heap()上溯,在此操作时,应该先push_back()
  • pop_heap():去顶:要pop_back()
  • sort_heap():排序后,不具备堆结构
  • make_heap():建堆

7.priority_queue

priority_queue就是具有优先级的queue,允许首部移出,尾端插入。缺省情况下利用一个max-heap完成,因此首部元素优先级最高.和queue一样,priority queue只有首部的元素有机会被外界取用。不提供遍历功能,也不提供迭代器.

template <class T, class Sequence = vector<T>, 
          class Compare = less<typename Sequence::value_type> >
class  priority_queue {
public:
  typedef typename Sequence::value_type value_type;
  typedef typename Sequence::size_type size_type;
  typedef typename Sequence::reference reference;
  typedef typename Sequence::const_reference const_reference;
protected:
  Sequence c;       //底层容器
  Compare comp;     //元素大小比较标准
public:
  priority_queue() : c() {}
  explicit priority_queue(const Compare& x) :  c(), comp(x) {}

  //以下用到的make_heap()、push_heap()、pop_heap()都是泛型算法
  //构造一个priority queue,首先根据传入的迭代器区间初始化底层容器c,然后调用
  //make_heap()使用底层容器建堆
  template <class InputIterator>
  priority_queue(InputIterator first, InputIterator last, const Compare& x)
    : c(first, last), comp(x) { make_heap(c.begin(), c.end(), comp); }
  template <class InputIterator>
  priority_queue(InputIterator first, InputIterator last) 
    : c(first, last) { make_heap(c.begin(), c.end(), comp); }

  bool empty() const { return c.empty(); }
  size_type size() const { return c.size(); }
  const_reference top() const { return c.front(); }
  void push(const value_type& x) {
    //先利用底层容器的push_back()将新元素推入末端,再重排heap
    __STL_TRY {
      c.push_back(x); 
      push_heap(c.begin(), c.end(), comp);
    }
    __STL_UNWIND(c.clear());
  }
  void pop() {
    //从heap内取出一个元素。但不是真正弹出,而是重排heap,然后以底层容器的pop_back()
    //取得被弹出的元素
    __STL_TRY {
      pop_heap(c.begin(), c.end(), comp);
      c.pop_back();
    }
    __STL_UNWIND(c.clear());
  }
};

猜你喜欢

转载自www.cnblogs.com/tingweichen/p/10743240.html
今日推荐